在使用微服务架构中,结合Zuul网关与RSA非对称加密实现鉴权中心,接下来介绍一下采用JWT+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,获取用户信息,无需访问授权中心
避免服务被暴露,使用JWT在服务间鉴权
授权中心
授权中心的主要职责:
- 用户鉴权:
- 接收用户的登录请求,通过用户中心的接口进行校验,通过后生成JWT
- 使用私钥生成JWT并返回
- 服务鉴权:微服务间的调用不经过Zuul,会有风险,需要鉴权中心进行认证
- 原理与用户鉴权类似,但逻辑稍微复杂一些
因为生成jwt,解析jwt这样的行为以后在其它微服务中也会用到,因此我们会抽取成工具。我们把鉴权中心进行聚合,一个工具module,一个提供服务的module
创建启动类:
1 |
|
配置application.yml
1 | server: |
修改路由:
1 | zuul: |
JWT通用的工具类:
1.RSA工具类:
1 | public class RsaUtils { |
2.常量类
其中定义了jwt中的payload的常用key
1 | public abstract class JwtConstans { |
3.对象工具类:
从jwt解析得到的数据是Object类型,转换为具体类型可能出现空指针,这个工具类进行了一些转换:
1 | public class ObjectUtils { |
4.JWT依赖
我们需要先在ly-auth-common中引入JWT依赖:
1 | <dependencies> |
代码:
1 | /** |
生成密钥
运行测试生成RSA公钥和私钥的代码:
运行之后,查看目标目录:
公钥和私钥已经生成了!
测试解析token

2.提供登录授权接口
接下来,我们需要在ly-auth-servcice编写对外提供登录授权服务。基本流程如下:
我们需要在授权中心生成真正的公钥和私钥。我们必须有一个生成公钥和私钥的secret,这个可以配置到application.yml中:
1 | ly: |
然后编写属性类,加载这些数据:
1 | (prefix = "ly.jwt") |
项目结构

2.5.Zuul的敏感头过滤
Zuul内部有默认的过滤器,会对请求和响应头信息进行重组,过滤掉敏感的头信息:
而这个SensitiveHeaders的默认值就包含了set-cookie:
全局设置:
zuul.sensitive-headers=
指定路由设置:
zuul.routes.<routeName>.sensitive-headers=zuul.routes.<routeName>.custom-sensitive-headers=true
思路都是把敏感头设置为null
3.4.刷新token
每当用户在页面进行新的操作,都应该刷新token的过期时间,否则30分钟后用户的登录信息就无效了。而刷新其实就是重新生成一份token,然后写入cookie即可。
那么问题来了:我们怎么知道用户有操作呢?
事实上,每当用户来查询其个人信息,就证明他正在浏览网页,此时刷新cookie是比较合适的时机。因此我们可以对刚刚的校验用户登录状态的接口进行改进,加入刷新token的逻辑。
1 | /** |
4.网关的登录拦截器
接下来,我们在Zuul编写拦截器,对用户的token进行校验,如果发现未登录,则进行拦截。
4.1.编写过滤器逻辑
基本逻辑:
- 获取cookie中的token
- 通过JWT对token进行校验
- 通过:则放行;不通过:则重定向到登录页
1 | /** |
所以,我们需要在拦截时,配置一个白名单,如果在名单内,则不进行拦截。
4.3.白名单
要注意,并不是所有的路径我们都需要拦截
在application.yaml中添加规则:
1 | ly: |
内容:
1 | (prefix = "ly.filter") |
在过滤器中的shouldFilter方法中添加判断逻辑:
代码:
1 |
|
再次测试:
可以优化的点
授权登录还需要完善:
1.需要引入权限控制系统
2.在AuthFilter中,应该判断权限
3.授权中心还可以做服务鉴权
未完待续
关于JWT与SpringBoot的简单授权使用就到这里结束了,欢迎有疑问和想法的朋友交流 ^_^