单点登录方案分析学习
1.系统都在同一域名下的简单单点登录方案:
方案一 用父域cookie实现
cookie作用域由domain和path两个属性共同决定
-
我们将domain设为当前域的父域域名,即设为父域的cookie,父域cookie为子域所共享/子域会自动继承父域中的cookie。
-
然后只需要将sessionId(或者token)保存到父域中就可以了,这样所有的子域都能访问到这个cookie了
但要求各系统的域名都建立在共同的域名之下,如map.baidu和tieba.baidu。
2.不同域名下的单点登录方案:
方案一 认证中心
图示:
-
用户访问系统1的受保护资源,系统1发现用户未登录,跳转至sso认证中心,并将自己的地址作为参数
-
sso认证中心发现用户未登录,将用户引导至登录页面
-
用户输入用户名密码提交登录申请s
-
so认证中心校验用户信息,创建用户与sso认证中心之间的会话,称为全局会话,同时创建授权令牌
-
sso认证中心带着令牌跳转会最初的请求地址(系统1)
-
系统1拿到令牌,去sso认证中心校验令牌是否有效
-
sso认证中心校验令牌,返回有效,注册系统1
-
系统1使用该令牌创建与用户的会话,称为局部会话,返回受保护资源
-
用户访问系统2的受保护资源
-
系统2发现用户未登录,跳转至sso认证中心,并将自己的地址作为参数
-
sso认证中心发现用户已登录,跳转回系统2的地址,并附上令牌
-
系统2拿到令牌,去sso认证中心校验令牌是否有效
-
sso认证中心校验令牌,返回有效,注册系统2
-
系统2使用该令牌创建与用户的局部会话,返回受保护资源用户登录成功之后,会与sso认证中心及各个子系统建立会话,用户与sso认证中心建立的会话称为全局会话
-
用户与各个子系统建立的会话称为局部会话,局部会话建立之后,用户访问子系统受保护资源将不再通过sso认证中心
全局会话与局部会话有如下约束关系:
-
局部会话存在,全局会话一定存在
-
全局会话存在,局部会话不一定存在
-
全局会话销毁,局部会话必须销毁
全局会话与局部会话的区别:
-
全局会话是SSO统一认证中心的全局会话
-
局部会话是子系统独有的会话,如果存在局部会话则可以直接访问受保护的资源无需请求认证中心做认证。
单点登录系统,存在全局会话和局部会话,全局会话由sso server维护,局部会话由具体的子系统维护。
用户登录成功之后,会与sso认证中心及各个子系统建立会话,用户与sso认证中心建立的会话称为全局会话,用户与各个子系统建立的会话称为局部会话,局部会话建立之后,用户访问子系统受保护资源将不再通过sso认证中心
sessionId:
-
sessionId用来追踪每个用户的会话,使用服务器生成的sessionId进行标识,用以区分用户。它存放在服务器的内存和客户机的cookie里。
-
sessionid 是一个会话的 key,浏览器第一次访问服务器会在服务器端生成一个 session,有一个 sessionID 和它对应,并返回给浏览器,这个 sessionID 会被保存在浏览器的会话 cookie 中。tomcat 生成的 sessionID 叫做 jsessionID。
-
sessionID 在访问 tomcat 服务器 HttpServletRequest 的 getSession(true) 的时候创建,tomcat 的 ManagerBase 类提供创建sessionID 的方法:随机数+时间+jvmid。Tomcat 的 StandardManager 类将 session 存储在内存中,也可以持久化到 file,数据库,memcache,redis等。
-
客户端只保存 sessionID 到 cookie 中,而不会保存 session。session 不会因为浏览器的关闭而删除,只能通过程序调用 HttpSession.invalidate() 或超时才能销毁。
服务端能存储多个sessionId么?
是的,服务器中维护着一个session池对象,对于每一个访问者来说都将随机不重复的产生一个sessionid对象存储在客服端的浏览器cookie中。
方案二 LocalStorage跨域(能让cookie跨域传递的办法)
首先从浏览器方面考虑:目前浏览器对 Cookie 的跨域限制越来越严格。Chrome 浏览器还给 Cookie 新增了一个 SameSite 属性,此举几乎禁止了一切跨域请求的 Cookie 传递(超链接除外),并且只有当使用 HTTPs 协议时,才有可能被允许在 AJAX 跨域请求中接受服务器传来的 Cookie。
所以我们开始从实现方面考虑:在前后端分离的情况下,完全可以不使用 Cookie,我们可以选择将 Session ID (或 Token )保存到浏览器的 LocalStorage 中,让前端在每次向后端发送请求时,主动将 LocalStorage 的数据传递给服务端。这些都是由前端来控制的,后端需要做的仅仅是在用户登录成功后,将 Session ID (或 Token )放在响应体中传递给前端。
在这样的场景下,单点登录完全可以在前端实现。前端拿到 Session ID (或 Token )后,除了将它写入自己的 LocalStorage 中之外,还可以通过特殊手段将它写入多个其他域下的 LocalStorage 中。
上面说的特殊手段,就是用iframe和postMessage实现,比如a,b两个域,可以通过在a中使用iframe包含入b的页面,然后利用postMessage将localStorage数据发送至b的页面,在b中利用window.onmessage进行监听。