SSO (Single Sign On)
什么是单点登录:
在大型的互联网公司中会有多个系统, 多个项目, 虽然这些项目都属于同一家公司, 但是项目本身其实都是独立的, 那多个系统可不可以实现共享同一份用户认证数据呢?
SSO 单点登录就是做这件事, 各个项目之间彼此相互信任, 在其中任意一个系统中进行登录, 用户的认证信息会被缓存在用户本地, 当用户去访问其他站点时, 可以复用这份认证信息, 而免去了重新登录的麻烦, 提高用户体验感
xxl 单点登录实现的逻辑
其实市面上的 SSO 框架还是挺多的, xxl 是国人写的, 代码还是挺容易懂的, 对了解 SSO 的实现流程也是比较有帮助的
第二点 : 这个项目中会有大量的操作 HttpServletRequest 以及 HttpServletResponse 的代码, 我们从中肯定能学习到编码的技巧, 再不济也能收获到大量跟 request , reponse, jedis 以及往浏览器写入 cookie, 重定向等逻辑, 值得学习一下封装成工具类使用
xxl 的官网是: https://www.xuxueli.com/xxl-sso/
整体的实现思路就是 URL + 对 Cookie 或者是 token 的读写实现的跨域, 这时一种怎么样的实现方式呢? 这就和浏览器对 cookie 的处理有关了, 当我们使用浏览访问某个站点时, 后台的逻辑可能会往浏览器中写入 cookie, 这个 cookie 的作用大家都知道, 就是一种身份标识, 当用户再次访问相同的站点时, 浏览器会自动的携带着这个站点对应的域名下面的 cookie
就像下面的图中一样, 标识, 这个 cookie 属于 xxlssoclient1.com 换句话说, 就是用户访问其他站点时是不会携带这个 cookie 的
从上面的分析中我们可以看出, 其实单点登录的局限性很明显, 不能跨域浏览器, 因为授权中心的凭证就是存放在用户的浏览器中的 cookie
言归正传
用户请求登录页
服务端一启动首先会先初始化过滤器, 使用这个过滤器将过滤用户的所有的请求, 校验用户是否有权限访问当前系统, 如果没有权限的话, 就将用户的请求转发到授权中心, 转发的路径如下:
http://xxlssoserver.com:8080/xxl-sso-server/login?redirect_url=http://xxlssoclient1.com:8081/xxl-sso-web-sample-springboot/
添加 redirect_url 参数的意图很明显, 就是为了从授权中心还会重定向回来
如果授权中心发现, 当前访问的用户确实没有任何可用的信息, 就返回一个登录页面给用户
用户 登录
用户在登陆页面发送登陆的请求到授权中心, 会经过如下的流程
经过的流程我在上图中都标记出来了, 值得注意的是 第二步, 会将用户的授权签名提前写回到用户的浏览器中, 因为用户向访问的 Client 中存在拦截器, 专门拦截用户的请求中是否携带合法的签名, 在这里将用户的请求写入到浏览器中后, 下次用户在次访问 Client 时, 就有合法的身份了
第二个注意点就是 , 在授权中心发起了重定向的操作, 重定向的 URL 如下:
http://xxlssoclient1.com:8081/xxl-sso-web-sample-springboot/?xxl_sso_sessionid=1000_e92ca0cb494b40eaa8e87a3aceb50279
url 中会携带着 sessionId, 目的是保证了这次请求, 能顺利的经过 Client 中检验
用户访问彼此信任的其他应用是如何做到不用重复授权的, 如下图
假设 Client 的 URL 是:
http://xxlssoclient1.com:8081/xxl-sso-web-sample-springboot/
Client2 的 URL 是
http://xxlssoclient2.com:8081/xxl-sso-web-sample-springboot/
如果 Client 和 Client2 共享一个授权中心 , 那么我们在浏览器上先使用 Client 进行一次登录. 登录成功后返回登录页面
然后我们在这个浏览器上继续访问 Client2 的 URL, 大家可以看到, Client 和 Client2 的 URL 中的区别: 就是域名不同, 当然我现在是在本地修改 host 名字进行模拟 , 实际生产上也是这个样子, 比如一个大型互联网公司, 它肯定有不同的项目 , 不同的项目就有自己不同的域名 , 然后我们现在就实现了访问不同的域名依然能够完成登录
结合上图看, 用户去访问 Client2 时, 因为用户从来没有登录过, 所以被 Client2 的拦截器拦截下来了, 然后将用户的请求重定向到授权中心, 但是这次重定向可是很特别的, 因为它会携带上第一次访问 Client 时, 写入到用户浏览器的 Cookie, , 这就好办了, 授权是认识这个 Cookie 的, 于是授权中心拿着这个 cookie 从 Redis 中取出了用户的信息, 然后将为用户生成的授权 sessionId 写回用户的浏览器中, 这些写回的授权 id, 被浏览器存放在 http://xxlssoclient2.com 域名下面, 然后再将这个请求重定向回 Client2, 这次从定向回来的请求 URL 长成下面这样
http://xxlssoclient2.com:8081/xxl-sso-web-sample-springboot/?xxl_sso_sessionid=1000_6966ea25ae264a28aa3ffe3b89ca7c9a
携带了 sessionId, 整体一套流程走下来, 客户端也无需要进行重复登录... 实现了单点登录
单点注销
注销就是删除 Redis 缓存中用户的信息, (xxl 的实现中, 授权中心和所有的 Client 之间共享一个 Redis 数据库) 这样看, 其实删除也就比较简单了, 只要我们保证能将 Redis 中的缓存的用户的信息删除就 ok, 用户浏览器中的 cookie 删除与否其实意义不大, 因为 Redis 中没有和这个 cookie 中完全配对的 cookie 的话, 这个请求仍然会被框架打向登录页面
来源: https://www.cnblogs.com/ZhuChangwu/p/11997499.html