⭐⭐⭐ Spring Boot 项目实战 ⭐⭐⭐ Spring Cloud 项目实战
《Dubbo 实现原理与源码解析 —— 精品合集》 《Netty 实现原理与源码解析 —— 精品合集》
《Spring 实现原理与源码解析 —— 精品合集》 《MyBatis 实现原理与源码解析 —— 精品合集》
《Spring MVC 实现原理与源码解析 —— 精品合集》 《数据库实体设计合集》
《Spring Boot 实现原理与源码解析 —— 精品合集》 《Java 面试题 + Java 学习指南》

摘要: 原创出处 苏三说技术 「苏三」欢迎转载,保留摘要,谢谢!


🙂🙂🙂关注微信公众号:【芋道源码】有福利:

  1. RocketMQ / MyCAT / Sharding-JDBC 所有源码分析文章列表
  2. RocketMQ / MyCAT / Sharding-JDBC 中文注释源码 GitHub 地址
  3. 您对于源码的疑问每条留言都将得到认真回复。甚至不知道如何读源码也可以请教噢。
  4. 新的源码解析文章实时收到通知。每周更新一篇左右。
  5. 认真的源码交流微信群。

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

传统Session的致命缺陷:

多个服务无法共享Session。

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

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

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

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

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

2.常见的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);
}

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

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

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

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

三大核心优势:

  • 一行代码实现登录鉴权
// 登录
StpUtil.login(10001);

// 鉴权
@SaCheckPermission("user:delete")
public void deleteUser(Long id) {
// 业务代码
}
  • 内置会话管理
// 查询所有会话
List<String> sessionList = StpUtil.searchSessionId("user:*", 0, 10);
  • 踢人下线机制
// 根据账号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网关统一鉴权

该方案是微服务的标配。

架构设计:

响应式鉴权过滤器:

public class AuthFilter implementsGlobalFilter {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
// 1. 提取Token
Stringtoken = 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
JWEHeaderheader =new JWEHeader.Builder(JWEAlgorithm.A256GCMKW,
EncryptionMethod.A256GCM).build();

// 2. 创建Payload
Payloadpayload =new Payload(new JSONObject()
.put("sub", user.getId())
.put("ssn", encrypt(user.getSsn()))); // 敏感信息加密

// 3. 加密Token
JWEObject jwe= newJWEObject(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

适用场景:

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

3.性能压测对比

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

4.安全攻防

4.1 四大攻击手段及防御

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.方案如何选型?

总结

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

微服务安全如同城堡防御——单一的护城河无法阻挡所有入侵,需要城墙、箭塔、卫兵的多层防护。

没有绝对安全的系统,只有不断提高的攻击成本。

文章目录
  1. 1. 1. 为什么必须做Token鉴权?
  2. 2. 2.常见的Token鉴权方案
    1. 2.0.1. 方案1:基础JWT+Redis方案
      1. 2.0.1.1. 核心架构:
      2. 2.0.1.2. 致命陷阱:
      3. 2.0.1.3. 正确实现:
    2. 2.0.2. 方案2:OAuth2.0授权框架
      1. 2.0.2.1. OAuth2.0包含了4种授权模式:
      2. 2.0.2.2. Spring Boot配置示例:
    3. 2.0.3. 方案3:Sa-Token轻量级框架
      1. 2.0.3.1. 三大核心优势:
      2. 2.0.3.2. 网关集成方案:
    4. 2.0.4. 方案4:API网关统一鉴权
      1. 2.0.4.1. 架构设计:
      2. 2.0.4.2. 响应式鉴权过滤器:
      3. 2.0.4.3. 性能优化技巧:
    5. 2.0.5. 方案5:Token中继模式
    6. 2.0.6. 方案6:JWE加密令牌
    7. 2.0.7. 方案7:双向TLS认证
  • 3. 3.性能压测对比
  • 4. 4.安全攻防
    1. 4.0.1. 4.1 四大攻击手段及防御
    2. 4.0.2. 4.2 审计日志必备字段
  • 5. 5.方案如何选型?
  • 6. 总结