Spring Cloud Security实现单点登录(JWT+RSA)

Spring Cloud下的微服务权限分别为三块:用户认证用户权限服务校验,下面主要分析用户认证的思路和源码。

传统的单体应用可能习惯了session的存在,而到了Spring cloud的微服务化后,session虽然可以采取分布式会话来解决,但终究不是上上策。开始有人推行Spring Cloud Security结合很好的OAuth2,后面为了优化OAuth 2中Access Token的存储问题,提高后端服务的可用性和扩展性,有了更好Token验证方式JWT(JSON Web Token)。这里要强调一点的是,OAuth2和JWT这两个根本没有可比性,是两个完全不同的东西。 OAuth2是一种授权框架,而JWT是一种认证协议。

JWT,全称是Json Web Token, 是JSON风格轻量级的授权和身份认证规范,
可实现无状态、分布式的Web应用授权;官网:https://jwt.io

JWT包含三部分数据:
–Header:头部,通常头部有两部分信息:

  • 声明类型,这里是JWT
  • 加密算法,自定义
    我们会对头部进行base64加密(可解密),得到第一部分数据

–Payload:载荷,就是有效数据,一般包含下面信息:

  • 用户身份信息(注意,这里因为采用base64加密,可解密,因此不要存放敏感信息)
  • 注册声明:如token的签发时间,过期时间,签发人等
    这部分也会采用base64加密,得到第二部分数据

–Signature:签名,是整个数据的认证信息。一般根据前两步的数据,再加上服务的的密钥(secret)
(不要泄漏,最好周期性更换),通过加密算法生成。用于验证整个数据完整和可靠性

#JWT交互流程步骤:

  • 1、用户登录
  • 2、服务的认证,通过后根据secret生成token
  • 3、将生成的token返回给浏览器
  • 4、用户每次请求携带token
  • 5、服务端利用公钥解读jwt签名,判断签名有效后,从Payload中获取用户信息
  • 6、处理请求,返回响应结果
    因为JWT签发的token中已经包含了用户的身份信息,并且每次请求都会携带,
    这样服务的就无需保存用户信息,甚至无需去数据库查询,完全符合了Rest的无状态规范。

#非对称加密
加密技术是对信息进行编码和解码的技术,编码是把原来可读信息(又称明文)译成代码形式(又称密文),
其逆过程就是解码(解密),加密技术的要点是加密算法,加密算法可以分为三类:

–对称加密,如AES、BASE64

  • 基本原理:将明文分成N个组,然后使用密钥对各个组进行加密,形成各自的密文,最后把所有的分组密文进行合并,形成最终的密文。
  • 优势:算法公开、计算量小、加密速度快、加密效率高
  • 缺陷:双方都使用同样密钥,安全性得不到保证

–非对称加密,如RSA

  • 基本原理:同时生成两把密钥:私钥和公钥,私钥隐秘保存,公钥可以下发给信任客户端
    • 私钥加密,持有私钥或公钥才可以解密
    • 公钥加密,持有私钥才可解密
  • 优点:安全,难以破解
  • 缺点:算法比较耗时

–不可逆加密,如MD5,SHA

  • 基本原理:加密过程中不需要使用密钥
    输入明文后由系统直接经过加密算法处理成密文,这种加密后的数据是无法被解密的,无法根据密文推算出明文。

RSA算法历史:
1977年,三位数学家Rivest、Shamir 和 Adleman 设计了一种算法,可以实现非对称加密。这种算法用他们三个人的名字缩写:RSA

#没有RSA加密时
在这里插入图片描述

  • 1、用户请求登录
  • 2、Zuul将请求转发到授权中心,请求授权
  • 3、授权中心校验完成,颁发JWT凭证
  • 4、客户端请求其它功能,携带JWT
  • 5、Zuul将jwt交给授权中心校验,通过后放行
  • 6、用户请求到达微服务
  • 7、微服务将jwt交给鉴权中心,鉴权同时解析用户信息
  • 8、鉴权中心返回用户数据给微服务
  • 9、微服务处理请求,返回响应

#结合RSA的鉴权
在这里插入图片描述

  • 我们首先利用RSA生成公钥和私钥。私钥保存在授权中心,公钥保存在Zuul和各个微服务
  • 用户请求登录
  • 授权中心校验,通过后用私钥对JWT进行签名加密
  • 返回jwt给用户
  • 用户携带JWT访问
  • Zuul直接通过公钥解密JWT,进行验证,验证通过则放行
  • 请求到达微服务,微服务直接用公钥解析JWT,获取用户信息,无需访问授权中心

1、登录一个账号限制该账号再次在别的地方登录简单。
1)登录授权时:
每次在登录授权前先判断redis里面是否已经存在该用户信息?
如果存在禁止登录,如果不存在则用jwt生成token然后往redis里存入
用户信息(过期时间和token的过期时间相同)允许登录。
2)鉴权时:
使用jwt鉴权然后刷新redis里面用户信息的过期时间。

2、要实现登录一个账号在别的地方再次登录时挤掉上一次登录状态怎么实现?
1)登录授权时:
先判断redis里面是否已经存在该用户信息(userid)?
如果存在给user设置一个登录状态码(UUID随机码或机器ip),然后用jwt给该用户
重新生成token并存入redis,允许该次登录。如果不存在给user设置一个登录状态码
(随机码或机器ip),然后用jwt生成token并存入redis,允许该次登录。

鉴权时:
先用jwt鉴权,解析token里面user的状态码和redis里面的码是否一样?
如果一样则认证成功,如果不一样则认证失败。

CAS单点登录原理:
在这里插入图片描述
每次用户先访问SSO客户端,SSO客户端拿着用户信息去SSO授权中心授权或鉴权,
SSO授权中心返回结果到SSO客户端,SSO客户端在处理结果返回到用户。

  1. 访问服务:SSO客户端发送请求访问应用系统提供的服务资源。
  2. 定向认证:SSO客户端会重定向用户请求到SSO服务器。
  3. 用户认证:用户身份认证。
  4. 发放票据:SSO服务器会产生一个随机的Service Ticket。
  5. 验证票据:SSO服务器验证票据Service Ticket的合法性,验证通过后,允许客户端访问服务。
  6. 传输用户信息:SSO服务器验证票据通过后,传输用户认证结果信息给客户端。

猜你喜欢

转载自blog.csdn.net/weixin_40682142/article/details/86597378