相关技术
传统登录
登录web系统后将用户信息保存在session中,sessionId写入浏览器的cookie中,每次访问系统,浏览器自动携带此cookie,服务端根据此sessionId取到相应的session,若为空则表示登录已失效,不为空则表示用户已登录,不需要用户再次输入用户名密码。
单点登录
单点登录是一种多站点共享登录访问授权机制,访问用户只需要在一个站点登录就可以访问其它站点需要登录访问的资源(url)。用户在任意一个站点注销登录,则其它站点的登录状态也被注销。简而言之就是:一处登录,处处登录。一处注销,处处注销。
spring-security + OAuth2 完美解决了完全跨域的问题。
单点登录时序图
看完上面的时序图,大家应该明白,使用OAuth2整合的单点登录本质上还是利用cookie + session的方式,虽然客户端和(服务端)认证中心交互采用的是JWT的方式,但浏览器和客户端还是采用cookie+session的方式。
整合SSO认证中心
1. 引入核心依赖
1 | <dependency> |
2. Security的核心配置文件
1 | 4j |
3. 配置基于OAuth2 的授权服务
1 | /** |
配置说明:
1. 此处把授权服务器和资源服务器一起配置了,可分开配置,如若不配置资源服务器,则在客户端无法通过获取的accessToken和服务端交互(登录和登出除外,@EnableOAuth2Sso注解做了自动处理),当然如果你的项目登录、登出够用了,也可不配置。
2. 本文采用的是数据库的方式存储OAuth的客户端信息,内存的方式也在文中提供了,采用JWT的方式实现TokenStore,熟悉OAuth2 的朋友应该知道,有4种方式来配置tokenStore,详情请移步这里tokenStore详解, 虽然我们也使用数据库来存储客户端的配置信息,但是因为使用的jwtTokenStore,access_token等信息都蕴藏在JWT里面,所以数据库只需要一张oauth_client_details表就行了,不需要存储授权码和access_token等信息。
3. 引入userDetailsService,是为了将OAuth2签发的access_token和系统的用户绑定起来,这样,此token就具有了系统用户所具有的访问权限。(有人说,这样绑定后,只要系统用户的session没有失效,token就会自动刷新,不会过期,经测试,token还是会过期,但应该还是有某种其他的联系,有兴趣的小伙伴可以深度研究)
4. 单点退出
原理: 用户在某个客户端执行退出操作后,通知认证中心和其他客户端,使他们也触发用户退出的相应操作,这就是单点退出。
遇到的问题: @EnableOAuth2Sso
只帮我们实现了通知认证中心退出的操作,此时浏览器和各个客户端建立的session
依旧有效,那怎样才能通知客户端呢?。
解决方案: 熟悉spring-security
的朋友都知道,security
鉴权时会拦截每一个访问的URL,判断用户是否登录,以及用户是否有此URL访问的权限,基于此,我们可在此过程中插入对用户是否在其他客户端退出的判断。在用户登录时,先到认证中心授权认证,登录成功的同时,认证中心将用户具有的权限信息(以用户名为key,权限信息作为value)存入到客户端能够访问的redis中,用户退出时,由认证中心去删除redis该用户的权限信息即可。用户访问客户端期间,一旦客户端的security取不到redis
中用户的权限信息了,即表示用户已在其他客户端退出了。
详情可参考我的 单点登录客户端 这篇博客。