如何基于Spring实现网关层不透明令牌与JWT映射的微服务认证授权方案
(本项目为大学课程项目,安全性要求略低于真实生产环境,仅实现API无前端部分)
实现方案
你需要的「对外返回不透明令牌、内部微服务间用JWT交互」的模式核心逻辑为:用户登录时认证中心生成不透明随机字符串和对应绑定的JWT,存入共享存储后仅对外返回不透明令牌;网关收到用户携带不透明令牌的请求后,查存储取出对应JWT透传给下游,下游直接本地校验JWT即可,无需额外请求依赖。
1. 认证中心实现
- 用户登录校验账号密码通过后,生成两类令牌:
- 不透明令牌:直接用
UUID.randomUUID().toString().replace("-","")生成32位随机字符串即可,过期时间和绑定的JWT保持一致 - 标准JWT:写入用户ID、权限、角色等业务需要的声明,推荐用RSA256非对称算法签名,完全规避JWT被篡改的风险;课程项目简化也可以用HS256对称签名,只要保证密钥不对外泄露即可
- 不透明令牌:直接用
- 将「不透明令牌 -> JWT」的映射关系写入Redis,设置和JWT一致的过期时间,无需持久化,数据丢失最多触发用户重新登录
- 登录接口仅返回不透明令牌给调用端,不返回JWT任何内容
2. Spring Cloud Gateway 令牌转换逻辑实现
自定义全局过滤器,优先级设置在路由转发之前,核心逻辑为提取用户传的不透明令牌,替换成对应JWT后透传给下游,核心代码示例如下:
@Component public class TokenTranslateFilter implements GlobalFilter, Ordered { @Autowired private StringRedisTemplate stringRedisTemplate; private static final String AUTH_HEADER = "Authorization"; private static final String BEARER_PREFIX = "Bearer "; private static final String TOKEN_KEY_PREFIX = "opaque_token:"; @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { ServerHttpRequest request = exchange.getRequest(); String authHeader = request.getHeaders().getFirst(AUTH_HEADER); // 校验是否携带合法Bearer令牌 if (authHeader == null || !authHeader.startsWith(BEARER_PREFIX)) { exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED); return exchange.getResponse().setComplete(); } String opaqueToken = authHeader.substring(BEARER_PREFIX.length()); String jwt = stringRedisTemplate.opsForValue().get(TOKEN_KEY_PREFIX + opaqueToken); if (jwt == null) { exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED); return exchange.getResponse().setComplete(); } // 替换请求头为内部用JWT ServerHttpRequest newRequest = request.mutate() .header(AUTH_HEADER, BEARER_PREFIX + jwt) .build(); return chain.filter(exchange.mutate().request(newRequest).build()); } @Override public int getOrder() { // 优先级设为最高,在所有路由逻辑之前执行 return -100; } }
3. 下游微服务JWT校验实现
- 所有内部微服务统一引入
spring-boot-starter-oauth2-resource-server依赖 - 配置文件里指定JWT的验签公钥(HS256则配置对称密钥),不需要连接Redis也不需要调用认证中心,直接本地校验JWT签名和过期时间即可
- 业务逻辑直接从Spring Security上下文获取用户权限、ID等信息即可,和直接用JWT的开发逻辑完全一致,无需额外适配
课程项目简化优化点
- 不需要搭建专业认证中心,直接写独立的用户服务实现登录和令牌生成逻辑即可
- 如果不想部署Redis,可改用Caffeine本地缓存存储令牌映射,只要网关是单实例部署就完全可用,开发调试更简单
内容的提问来源于stack exchange,提问作者Jose Carlos Padilla Cancio
相关产品推荐
相关产品推荐

