首页 - 技术 - 【第173期】面试官:谈谈实现单点登录的三种方式

【第173期】面试官:谈谈实现单点登录的三种方式

2023-10-04 16:15
2022年5月17日下午3:56 • 面试问题 • 阅读2 点击上方“Java面试题精选”,关注公众号 面试时画图,查漏补缺 >>番外:往期面试题,10个为单位放在这个公众号菜单栏->面试题,有需要的欢迎阅读 阶段总结合集:001至150期总结,方便阅读,持续更新... 前言 在B/S系统中,登录功能通常是基于cookie来实现的。当用户登录成功后,一般会在Session中记录登录状态,或者给用户发放一个Token。无论哪种方式,客户端都需要保存一些信息(Session ID或者Token),并且要求客户端在后续的每次请求中携带它们。在这样的场景下,使用cookie无疑是最方便的,所以我们通常会在cookie中保存Session ID或者Token。服务器收到请求后,通过验证cookie中的信息来判断用户是否登录。 单点登录(SSO)是指在同一账户平台下的多个应用系统中,用户只需登录一次即可访问所有相互信任的应用系统。例如,百度贴吧和百度地图是百度旗下两个不同的应用系统。如果用户已经登录了百度贴吧,访问百度地图时不需要再次登录,那么就说明百度贴吧和百度地图之间存在差距。实现了单点登录。 单点登录的本质是在多个应用系统之间共享登录状态。如果Session中记录了用户的登录状态,要实现共享登录状态,必须先共享Session。例如,可以将Session序列化到Redis中,让多个应用系统共享同一个Redis,直接读取Redis来获取Session。当然,仅此还不够,因为不同的应用系统有不同的域名。虽然Session是共享的,但是由于Session ID往往保存在浏览器cookie中,所以存在范围限制,不能跨域名传输,也就是说,当用户登录www.gsm-guard.net时,Session ID只有当浏览器访问www.gsm-guard.net时,才会在请求头中自动携带Session ID,而当浏览器访问www.gsm-guard.net时,不会携带Session ID。 。实现单点登录的关键是如何跨多个域共享Session ID(或Token)。 实现方法一:父域Cookie 在详细实现之前,我们先来说一下Cookie的范围。 cookie的范围由domain属性和path属性决定。域属性的有效值为当前域或其父域的域名/IP地址。在Tomcat中,domain属性默认为当前域的域名/IP地址。 path属性的有效值为以“/”开头的路径。在 Tomcat 中,path 属性默认为当前 Web 应用程序的上下文路径。 如果 cookie 的域属性设置为当前域的父域,则该 cookie 被视为父域 cookie。 Cookie 的一个特点是父域中的 Cookie 被子域共享。换句话说,子域自动继承父域的cookie。 利用Cookie的这一特性,不难想到将Session ID(或Token)保存在父域中。没错,我们只需要将cookie的domain属性设置为父域的域名(主域名),将cookie的path属性设置为根路径,这样所有子域应用都可以访问到这个cookie 。但这要求应用系统的域名建立在一个共同的主域名下,例如www.gsm-guard.net、www.gsm-guard.net。它们都是建立在主域名www.gsm-guard.net下,因此都可以采用这种方式来实现单点登录。 总结:这种实现方式比较简单,但是不支持跨主域名。 实施方式二:认证中心 我们可以部署一个认证中心,它是一个独立的Web服务,专门负责处理登录请求。用户在认证中心统一登录。登录成功后,认证中心记录用户的登录状态,并将Token写入Cookie中。 (注意,该cookie属于认证中心,应用系统无法访问。) 应用系统检查当前请求是否有token。如果没有,则说明用户尚未登录当前系统,页面将被重定向至认证中心。由于该操作会自动带上认证中心的cookie,因此认证中心可以根据cookie知道用户是否已经登录。如果认证中心发现用户没有登录,则返回登录页面,等待用户登录。如果发现用户已经登录,则不会让用户再次登录,而是会跳转回目标URL并生成一个Token拼接在目标URL后面并发送给目标应用系统。 应用系统获得Token后,需要与认证中心确认Token的合法性,防止用户伪造。确认后,应用系统记录用户的登录状态,并将Token写入cookie中,然后允许此次访问。 (注意,这个cookie属于当前应用系统,其他应用系统无法访问。)当用户再次访问当前应用系统时,会自动带上这个Token。应用系统验证Token,发现用户已经登录,那么就不会认证中心发生什么事了? 这里介绍一下两个认证中心的开源实现: Apereo CAS 是企业级单点登录系统,其中 CAS 的意思是“中央身份验证服务”。它原本是耶鲁大学实验室的一个项目,后来转移到JASIG组织,该项目更名为JASIG CAS。后来该组织并入 Apereo 基金会,项目更名为 Apereo CAS。 XXL-SSO是大众点评工程师徐雪日开发的一个简单的单点登录系统。代码比较简单,没有安全控制。因此,不建议直接应用于项目中。在此列出,仅供参考。 总结:这种实现方式比较复杂,支持跨域,扩展性好,是单点登录的标准做法。 实现方法三:LocalStorage跨域 前面我们说过,实现单点登录的关键是如何在多个域中共享Session ID(或者Token)。 父域cookie确实是一个很好的解决方案,但是不支持跨域。那么跨域传递cookie有什么奇怪的技巧吗?不幸的是,浏览器对跨域 cookie 的限制越来越严格。 Chrome浏览器还为Cookies添加了SameSite属性,该属性禁止几乎所有跨域请求Cookie传输(超链接除外),并且仅在使用HTTPs协议时的AJAX跨域请求中允许。接受来自服务器的cookie。 不过,当前后端分离时,就不需要使用cookie了。我们可以选择将Session ID(或Token)保存到浏览器的LocalStorage中,这样前端每次向后端发送请求时都会主动保存LocalStorage。数据被传递到服务器。这些都是由前端控制的。后端需要做的就是将Session ID(或Token)放入响应体中,并在用户成功登录后将其传递给前端。 在这样的场景下,单点登录完全可以在前端实现。前端拿到Session ID(或者Token)后,除了写入自己的LocalStorage之外,还可以通过特殊手段写入到其他多个域的LocalStorage中。 关键代码如下: // 获取 tokenvar token = result.data.token; // 动态创建一个不可见的 iframe,并在 iframe 中加载跨域 HTMLvar iframe = document.createElement("iframe");iframe.src = "http://www.gsm-guard.net/localstorage.html";document.body . append(iframe);// 使用 postMessage() 方法将 token 传递给 iframesetTimeout(function () { iframe.contentWindow.postMessage(token, "http://www.gsm-guard.net");}, 4000);setTimeout(函数 () { iframe.remove();}, 6000);// 将事件侦听器绑定到此 iframe 加载的 HTML。事件触发时,将接收到的token数据写入localStoragewindow.addEventListener('message', function (event) { localStorage.setItem('token ', www.gsm-guard.net)}, false); 前端通过iframe+postMessage()将同一个Token写入多个域的LocalStorage。前端每次向后端发送请求时,都会主动从LocalStorage中读取Token并携带在请求中。这样就可以实现同一个Token被多个域共享。 总结:这种实现完全由前端控制,几乎不需要后端参与。它还支持跨域。 补充:域名分类 从专业角度看(根据《计算机网络》中的定义),.com和.cn是一级域名(也叫顶级域名),.www.gsm-guard.net和www.gsm-guard.net是二级域名、www.gsm-guard.net、www.gsm-guard.net为三级域名,以此类推,N级域名为N-1级域名的直接子域名。 从用户的角度来看,能够支持独立备案的主域名一般称为一级域名。例如,www.gsm-guard.net、www.gsm-guard.net都可以称为一级域名。在主域名下创建的直接子域名称为二级域名。例如www.gsm-guard.net就是二级域名。 为了避免歧义,我将使用“主域名”而不是“一级域名”。 来源:www.gsm-guard.net/yonghengzh/p/13712729.html 而不是在网上搜索问题?还不赶快关注我们吧~ 版权声明:本文内容由网友自愿贡献,本文所表达的观点仅代表作者自己的观点。本网站仅提供信息存储空间服务,不拥有任何所有权,也不承担相关法律责任。如果您发现本站有任何涉嫌侵权/非法内容,请发送邮件举报。一经核实,该网站将立即删除。 本文由斑马博客整理。本文链接为:https://www.gsm-guard.net/index.php/post/7445.html