单点登录实现思路及自定义实现方案
单点登陆概念: single sign on 又称SSO,设计目标就是用户只需要登录一次即可在无需再次登录的情况下访问相关联的其它系统,
同时也是现在SOA架构中将功能模块微服务化中,统一登陆模块关键点。
常见实现思路:
用户登录成功后,将登录成功的用户信息存放到session或者缓存中,并返回与登录结果一对一关联的sessionId或者Token或自定义的信息到客户端,
客户端将返回的token等存储到cookie或者作为一个请求参数,在对其它系统进行请求的时候,请求头或者请求参数中跟上token
当系统接收需鉴权资源的请求时,从请求头或者请求参数中获取到token等信息,根据获取到的token信息从session或者缓存中获取到用户信息,
如果用户存在且有权限访问,则执行请求并返回请求结果,否则返回未登录或者相关错误信息。
自定义实现思路:
1. 定义登录系统白名单: 将需要使用单点登录的服务域名保存到数据库,在系统启动时增加到缓存,并在对白名单修改时刷新缓存
2.定义登录返回信息: 返回系统中唯一的token,还有像用户id,用户名,登录ip(安全考虑,后面会说明用处)等
3.登录: 在登录界面输入用户名、密码,验证码等后,进行登录验证,
4.生成token并缓存用户信息及关系:用户登录成功后生成第2步需要的对象,生成token并缓存用户信息及关系,如map中key为token,value为登录成功的用户信息
5.设置缓存过期时间: 登录成功后用户的缓存信息为了安全,应该根据一定的过期策略使其过期
6.定义登录检查filter:filter中首先需要获取到token,根据token从缓存中找到登录的用户信息,若存在登录信息,则修改过期时间为XXX分钟后,并将用户信息放到request中
7定义interceptor检查: 从request中获取用户信息,如果没有重定向到登录页面或者未登录提示页面,若获取到了用户信息,则返回true继续请求
注意点:
1.尽量不要将用户登录后的信息放在session里面,否则分布式部署时又涉及到了session同步了
2.传递token方式:
a. 采用Cookie方式。 token信息对用户不可见,filter中获取时根据名字从cookie中获取
b. 采用参数方式。 token信息对用户可见,作为参数跟在请求地址中,filter中从请求参数中获取
如果采用a‘方式,则不用很麻烦的每次都在请求参数中跟上token,程序自动从cookie中获取了。但如果客户端禁用了cookie就不好了
如果采用b方式,则不用担心客户端对cookie的设置,但是每次都得在请求参数中跟上,且很容易暴露token信息
注意: 无论采用哪种方式传递,都能获取到用户的token信息,为了防止token被非法使用,可以很简单的在每次请求时将从缓存中获取到的用户信息中的ip地址和请求的ip地址进行比较,若相同,则认为是同一台电脑操作,否则认为是非法操作,后台需驳回请求并删除该用户缓存信息。
用户如果更换了电脑使用,就必须得重新登录,这也符合使用场景,而且token不会那么简单易记
在我负责的实际项目中,token是32的UUID来确保唯一性,根据token信息查找用户信息进行了两步操作:
1.通过token从缓存中找到对应的用户id根据加密后的值
2.通过解密后的id再从缓存中找到用户信息
所以,用户登录成功时,先把id加密作为key缓存用户信息;再缓存uuid和加密后的id的关系,
这么做主要是为了删除已经缓存的用户信息
如:A电脑登录了,又去B电脑登录,B电脑登录成了,找到了用户信息,将用户id加密作为key去缓存查找信息,存在便删除重新存储新的信息,
如果是直接存储的key是uuid,value是用户信息,则不容易轻易查找到。
当然这只是个人思路, 还可以根据一定规则生成token,token中加解密后就能获取到用户id啥的,根据需要自行变通吧