微服务Token鉴权的7种方案

大家好,我是苏三,又跟大家见面了。

前言

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

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

最近建了一些工作内推群,各大城市都有,欢迎各位HR和找工作的小伙伴进群交流,群里目前已经收集了不少的工作内推岗位。

扫码加苏三的微信:li_su223,备注:所在城市,即可进群。

picture.image

  1. 为什么必须做Token鉴权?

传统Session的致命缺陷

picture.image

多个服务无法共享Session。

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

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

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

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

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

2.常见的Token鉴权方案

方案1:基础JWT+Redis方案

该方案适合初创系统。

核心架构

picture.image

致命陷阱

  
// 错误示例:未校验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);  
}  

适用场景 :用户量<100万的中小型系统

方案2:OAuth2.0授权框架

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

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

picture.image

授权码模式流程

picture.image

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扩展 防止授权码截持攻击

方案3:Sa-Token轻量级框架

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

三大核心优势

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

  1. 内置会话管理
  
// 查询所有会话  
List<String> sessionList = StpUtil.searchSessionId("user:*", 0, 10);  

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

网关集成方案

  
@Bean  
public 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集群模式)

方案4:API网关统一鉴权

该方案是微服务的标配。

架构设计

picture.image

响应式鉴权过滤器

  
public class AuthFilter implements GlobalFilter {  
    @Override  
    public Mono<Void> filter(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);  
                });  
    }  
}  

性能优化技巧

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

方案5:Token中继模式

该方案适合服务链调用。

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

解决方案

picture.image

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的核心区别

picture.image

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认证

该方案是零信任架构。

工作流程

picture.image

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  

适用场景

  • 服务网格内部通信
  • 银行核心系统
  • 政府机密数据交换

3.性能压测对比

| 方案 | 平均延时 | CPU消耗 | 安全等级 | 适用场景 | | --- | --- | --- | --- | --- | | 基础JWT | 3ms | 15% | ★★☆ | 内部微服务 | | OAuth2.0 | 35ms | 40% | ★★★☆ | 第三方开放平台 | | Sa-Token | 5ms | 18% | ★★★ | 快速开发项目 | | 网关统一鉴权 | 8ms | 25% | ★★★☆ | 多语言混合架构 | | Token中继 | 12ms | 30% | ★★★ | 服务链调用 | | JWE加密 | 45ms | 60% | ★★★★☆ | 金融敏感数据 | | mTLS | 20ms | 50% | ★★★★★ | 零信任网络 |

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

4.安全攻防

4.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())

4.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;  // 操作时间  
}  

5.方案如何选型?

picture.image

总结

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

微服务安全如同城堡防御——
单一的护城河无法阻挡所有入侵,
需要城墙、箭塔、卫兵的多层防护。
没有绝对安全的系统,只有不断提高的攻击成本。

最后欢迎加入苏三的星球,你将获得:100万QPS短链系统、复杂的商城微服务系统、苏三AI项目、刷题吧小程序、秒杀系统、商城系统、秒杀系统、代码生成工具等8个项目的源代码、开发教程和技术答疑。

系统设计、性能优化、技术选型、底层原理、Spring源码解读、工作经验分享、痛点问题、面试八股文等多个优质专栏。

还有1V1免费修改简历、技术答疑、职业规划、送书活动、技术交流。

扫描下方二维码,可以优惠30元:

picture.image

目前星球已经更新了5800+篇优质内容,还在持续爆肝中.....

星球已经被官方推荐了3次,收到了小伙伴们的一致好评。戳我加入学习,已有1800+小伙伴加入学习。

0
0
0
0
评论
未登录
暂无评论