微服务中Token鉴权除了用JWT之外,还有什么方案?

B站影视 内地电影 2025-09-17 10:08 1

摘要:// 结合Redis校验Token状态public boolean validateToken(String token, UserDetails details) { String username = extractUsername(token); Str


前言

最近有读者问我:微服务中Token鉴权除了使用JWT之外,还有什么其他的方案?

今天这篇文章跟大家一起聊聊微服务Token鉴权的7种方案,希望对会有所帮助。

一、什么必须做Token鉴权?

传统Session的致命缺陷:

多个服务无法共享Session。

重复认证,导致系统性能严重下降。

2023年某电商平台发送安全事故:

GET /api/users/balance HTTP/1.1Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIn0.Gfx6VO9tcxwk6xqx9yYzSfebbeKDTHkQKh0xhu4nJE0

黑客通过XSS攻击窃取此Token后,在2小时内盗取5万用户余额,暴露三大漏洞:

Token未绑定IP/设备指纹敏感操作未二次认证无异常行为检测机制

二、常见的Token鉴权方案

方案1:基础JWT+Redis方案

该方案适合初创系统。

核心架构:

致命陷阱:

// 错误示例:未校验Token有效性public Claims parseJwt(String token) { return Jwts.parser .setSigningKey(SECRET_KEY) .parseClaimsJws(token) .getBody; // 若Token被注销仍能解析通过!}

正确实现:

// 结合Redis校验Token状态public boolean validateToken(String token, UserDetails details) { String username = extractUsername(token); String redisToken = redisTemplate.opsForValue.get("token:"+username); // 双重验证:签名有效且未注销 return (username.equals(details.getUsername) && !isTokenExpired(token) && token.equals(redisToken);}

适用场景:用户量

方案2:OAuth2.0授权框架

该方案是第三方接入的首选。

OAuth2.0包含了4种授权模式:

授权码模式流程:

Spring Boot配置示例:

spring: security: oauth2: client: registration: github: client-id:${GITHUB_CLIENT_ID} client-secret:${GITHUB_SECRET} scope:user:email,read:user provider: github: token-uri:https://github.com/login/oauth/access_token user-info-uri:https://api.github.com/user

关键点:必须使用PKCE扩展防止授权码截持攻击

该方案是的国产Token鉴权方案的精品。

三大核心优势:

1、一行代码实现登录鉴权

// 登录StpUtil.login(10001); // 鉴权@SaCheckPermission("user:delete")public void deleteUser(Long id) { // 业务代码}

2、内置会话管理

// 查询所有会话ListsessionList = StpUtil.searchSessionId("user:*", 0, 10);

3、踢人下线机制

// 根据账号ID踢人StpUtil.kickout(10001);// 根据Token值踢人StpUtil.kickoutByTokenValue("xxxx");

网关集成方案:

@Beanpublic SaReactorFilter saReactorFilter { return new SaReactorFilter .addInclude("/**") .setAuth(obj -> { SaRouter.match("/user/**").check(r -> StpUtil.checkPermission("USER")); SaRouter.match("/admin/**").check(r -> StpUtil.checkPermission("ADMIN")); });}

性能实测:QPS 12,000(Redis集群模式)

该方案是微服务的标配。

架构设计:

响应式鉴权过滤器:

public class AuthFilter implements GlobalFilter { @Override public Monofilter(ServerWebExchange exchange, GatewayFilterChain chain) { // 1. 提取Token String token = extractToken(exchange.getRequest); // 2. 响应式鉴权调用 return reactiveAuthService.validateToken(token) .flatMap(valid -> { if (!valid) { exchange.getResponse.setStatusCode(HttpStatus.UNAUTHORIZED); return exchange.getResponse.setComplete; } return chain.filter(exchange); }); }}

性能优化技巧:

本地缓存:使用Caffeine缓存验证结果批量验证:聚合10ms内请求统一鉴权热点Token特殊处理

方案5:Token中继模式

该方案适合服务链调用。

核心问题:服务A调用服务B时Token如何传递

解决方案:

Feign中继实现:

@FeignClient(name = "service-b")public interface ServiceBClient { @GetMapping("/data") Data getData(@Requestheader("Authorization") String token);}// 调用方public Data getData(String token) { // 原样传递Token return serviceBClient.getData("Bearer " + token); }

安全加固:使用JWT嵌套加密防止内部Token泄露

方案6:JWE加密令牌

该方案能保证金融级安全。

与JWT的核心区别:

Java生成示例:

public String createJwe(User user) throws JOSEException { // 1. 组装Header JWEHeader header = new JWEHeader.Builder(JWEAlgorithm.A256GCMKW, EncryptionMethod.A256GCM).build; // 2. 创建Payload Payload payload = new Payload(new JSONObject .put("sub", user.getId) .put("ssn", encrypt(user.getSsn))); // 敏感信息加密 // 3. 加密Token JWEObject jwe = new JWEObject(header, payload); jwe.encrypt(new AESEncrypter(SECRET_KEY.getBytes)); return jwe.serialize;}

适用场景:

支付凭证身份证号传输医疗健康数据

方案7:双向TLS认证

该方案是零信任架构。

工作流程:

Spring Boot配置:

server: ssl: key-store:classpath:server-keystore.p12 key-store-password:changeit key-alias:server client-auth:need# 关键配置 trust-store:classpath:client-truststore.p12 trust-store-password:changeit服务网格内部通信银行核心系统政府机密数据交换基础JWT3ms15%★★☆内部微服务OAuth2.035ms40%★★★☆第三方开放平台Sa-Token5ms18%★★★快速开发项目网关统一鉴权8ms25%★★★☆多语言混合架构Token中继12ms30%★★★服务链调用JWE加密45ms60%★★★★☆金融敏感数据mTLS20ms50%★★★★★零信任网络

测试环境:AWS c5.4xlarge 16核32GB × 3节点

四、安全攻防

1、四大攻击手段及防御

攻击类型防御方案代码实现Token窃取绑定设备指纹StpUtil.getToken.setExtra("deviceId", fingerprint)重放攻击Nonce校验+时间戳redis.opsForValue.setIfAbsent(nonce, "used", 5, TimeUnit.SECONDS)越权访问动态权限校验@SaCheckPermission("#user.id")Token破解定期轮换签名密钥Jwts.parserBuilder.setSigningKeyResolver(new KeyRotationResolver)

2、审计日志必备字段

为了保证系统的操作安全,我们需要增加审计日志表。

审计日志必备字段如下:

public class AuditLog { private String tokenId; // Token唯一标识 private String userId; // 用户ID private String operation; // 操作类型 private String resource; // 访问资源 private String clientIp; // 客户端IP private String deviceInfo; // 设备信息 private LocalDateTime time; // 操作时间}

五、方案如何选型?

初创期:基础JWT+Redis方案发展期:OAuth2.0+网关鉴权成熟期:JWE加密+双向TLS高级期:零信任架构+AI风控

来源:dbaplus社群一点号

相关推荐