谈谈单点登录?
1. 什么是单点登录?
2. 单点登录的实现;
3. 单点登录的延续性?
4. 踢掉线与挤掉线的实现;
什么是单点登录?
单点登录是在微服务中的一种安全校验方式;
在微服务中,根据功能和需求将项目划分成多个子服务;在最初的单体架构中,我们使用的是Session的方式实现的安全认证。
用户每次访问子服务都需要重新登录验证。
用户只需要验证一次,就可以访问所有的子服务。
Session的认证:
浏览器输入用户名密码;传入后台服务器,服务器根据用户名密码,去往数据库中查找用户数据进行校验,成功则返回数据,此时将用户信息存入session中,下次用户访问时,先判断session中有没有当前用户信息,如果有,则通过。
session的方式在微服务架构中会一些问题,在A子服务中,保存了session,但是下次访问的是B子服务,B子服务中没有保存session信息,这样会让用户再次登录!
单点登录的认证方式:
JWT:
JSON Web Token
JWT组成:
- 头部:储存基本信息;
- 载荷:一般用于存储当前用户的信息(角色、权限、基本信息);
- 签名:为了保证生成的token是安全的,需要用一个类似盐的东西生成。
浏览器登录页面传输用户名密码,后端接收后,去往数据库中查找用户信息,比对,如果成功,那么返回这个用户的信息。服务器根据用户信息生成Token,返回给浏览器,浏览器下次访问服务器时,携带Token进行访问,服务器解析Token就可以获得当前用户信息,并验证通过。
中心化管理与去中心化管理
去中心化:用户访问服务器时,转发给用户中心子服务进行Token解析验证身份信息,验证通过,转发给需要访问的服务;
中心化:服务器生成Token存储在Redis中,浏览器访问服务器时,将Redis中的Token取出,进行身份
校验,校验通过,验证通过!
用Redis中心化管理的好处在于:可以同时管理多个用户的Token信息;
单点登录的延续性?
一般登录业务,Token都需要生成过期时间,所以当我们访问服务器时,时间到了Token的失效时间,就会使得用户需要重新验证。
解决方案:
- 浏览器每次访问服务器,重新生成一个新的Token,将新Token返回给浏览器,浏览器下次访问携带新Token进行登录验证,这样就能做到Token延续;
- 长短Token
在浏览器访问服务器时,用户验证身份通过,生成两个Token,假设此时我们的业务为:用户30分钟未操作Token失效;那么生成TokenA,时效为30分钟,生成TokenB,时效为30~60分钟;浏览器中存放TokenA、TokenB、登录时间、最后一次访问时间;浏览器的下次请求距离最后一次访问时间,距离登录时间在30分钟内,那么浏览器携带TokenA进行访问;若超过30分钟,那么携带TokenB进行访问;服务器接收Token,判断是TokenA还是TokenB,如果是TokenA,解析Token,进行验证;如果是TokenB,那么就再次生成两个Token,返回给浏览器,刷新浏览器的登录时间为本次访问时间。
踢掉线和挤掉线
踢掉线:
**业务需求:**用户在A端登录成功后,在B端重新登录,那么A端的登录需要失效;
准备:Redis(key:用户id,value:Token)
用户在A端登录成功后,将Token信息存入Redis中,当用户在B端登录成功,先根据用户id查询Redis中有没有这个用户的Token信息,如果有,把当前时间作为slat,重新生成一个Token,将新生成的Token替换掉Redis中的Token,当A再次访问服务器时,将会验证失败,重新登录。
挤掉线
**业务需求:**一个用户账号,可以在5个不同的设备上进行登录;
准备:Redis
在redis中存储一个<key,set<String,String>>;用户账号在设备A中登录时,将A的ip地址作为key,生成的Token作为value,存入Redis的set集合中。用户在B、C、D、E设备上登录成功后,同样执行上述操作。此时用户账号已在5台不同设备上进行登录,这时,用户再次使用设备F登录,验证身份信息后,生成Token,存入Redis前,首先将B设备生成的Token信息,覆盖掉设备A在Redis中存储的Token信息,依次类推,设备F覆盖设备E的Token信息,此时设备A就需要重新验证身份信息了,实现挤掉线功能。