简单介绍
传统 JWT 的工作原理
JWT
(JSON Web Token) 是一种开放标准(RFC 7519),用于在各方之间安全地传输信息。传统的 JWT
主要包含三个部分:
- Header - 头部信息
- Payload - 载荷数据
- Signature - 签名信息
传统 JWT
采用签名机制来保证数据的完整性和来源可信,但其载荷内容是 Base64 编码的,这意味着任何人都可以解码查看其中的内容。
JWT 的不足之处
- 数据可见性:载荷内容虽经过签名但未加密,敏感信息容易泄露
- 隐私保护有限:无法满足对数据机密性的高要求场景
- 合规风险:在处理个人敏感信息时可能不符合数据保护法规
JWE 的优势
JWE
(JSON Web Encryption) 在 JWT
基础上增加了加密层,提供以下优势:
- 数据机密性:对整个载荷进行加密,确保内容不可见
- 更强安全性:结合签名和加密,提供双重保护
- 合规支持:满足 GDPR、HIPAA 等数据保护要求
与 JWT 的对比
特性 | JWT | JWE |
---|---|---|
数据保护 | 仅签名,内容可见 | 加密保护,内容不可见 |
安全级别 | 中等 | 高 |
性能开销 | 低 | 较高 |
适用场景 | 公开信息传输 | 敏感数据传输 |
实现复杂度 | 简单 | 复杂 |
java
// 普通 JWT 示例
String jwt = Jwts.builder()
.setSubject("user123")
.claim("role", "admin")
.signWith(secretKey)
.compact();
// JWE 示例
String jwe = Jwts.builder()
.setSubject("user123")
.claim("role", "admin")
.encryptWith(encryptionKey, JweAlgorithm.DIR, JweEncryption.A256GCM)
.compact();
使用场景
敏感数据传输
当需要在 JWT
中包含敏感信息时,如用户详细资料、权限列表等,使用 JWE
可以确保这些信息不会被第三方窃取。
合规性要求
在金融、医疗等行业,数据保护法规要求对敏感信息进行加密处理,JWE
可以满足这类合规性需求。
内部系统通信
微服务架构中,服务间传输包含业务敏感数据的令牌时,JWE
提供了更好的安全保障。
防止信息泄露
避免在日志、浏览器缓存中暴露用户敏感信息,防止中间人攻击获取载荷内容。
Spring Boot 应用中的实践
添加依赖
xml
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
<version>0.11.5</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
<version>0.11.5</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId>
<version>0.11.5</version>
<scope>runtime</scope>
</dependency>
配置 JWE 加密密钥
java
@Configuration
public class JweConfig {
@Bean
public SecretKey jweKey() {
// 生成 256 位密钥用于 AES 加密
return Keys.secretKeyFor(SignatureAlgorithm.HS512);
}
}
创建 JWE Token
java
@Service
public class TokenService {
@Autowired
private SecretKey jweKey;
public String createJweToken(String username, List<String> roles) {
return Jwts.builder()
.setSubject(username)
.claim("roles", roles)
.claim("created", System.currentTimeMillis())
.encryptWith(jweKey, JweAlgorithm.DIR, JweEncryption.A256GCM)
.setExpiration(new Date(System.currentTimeMillis() + 3600000)) // 1小时过期
.compact();
}
public Claims parseJweToken(String jweToken) {
return Jwts.parserBuilder()
.decryptWith(jweKey)
.build()
.parseEncryptedClaims(jweToken);
}
}
在安全过滤器中使用
java
@Component
public class JweAuthenticationFilter extends OncePerRequestFilter {
@Autowired
private TokenService tokenService;
@Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response,
FilterChain filterChain) throws ServletException, IOException {
String authHeader = request.getHeader("Authorization");
if (authHeader != null && authHeader.startsWith("Bearer ")) {
String jweToken = authHeader.substring(7);
try {
Claims claims = tokenService.parseJweToken(jweToken);
String username = claims.getSubject();
List<String> roles = (List<String>) claims.get("roles");
// 创建认证对象
UsernamePasswordAuthenticationToken authentication =
new UsernamePasswordAuthenticationToken(username, null,
roles.stream().map(SimpleGrantedAuthority::new).collect(Collectors.toList()));
SecurityContextHolder.getContext().setAuthentication(authentication);
} catch (JwtException e) {
logger.error("JWE token 解析失败", e);
}
}
filterChain.doFilter(request, response);
}
}
控制器中的应用
java
@RestController
@RequestMapping("/api")
public class UserController {
@Autowired
private TokenService tokenService;
@PostMapping("/login")
public ResponseEntity<String> login(@RequestBody LoginRequest request) {
// 验证用户凭据
if (authenticate(request.getUsername(), request.getPassword())) {
List<String> roles = getUserRoles(request.getUsername());
// 创建 JWE token
String jweToken = tokenService.createJweToken(request.getUsername(), roles);
return ResponseEntity.ok(jweToken);
}
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build();
}
@GetMapping("/profile")
public ResponseEntity<UserProfile> getProfile(Authentication authentication) {
String username = authentication.getName();
UserProfile profile = getUserProfile(username);
return ResponseEntity.ok(profile);
}
}
总结
JWE
作为 JWT
的增强版本,在数据安全性方面提供了显著优势:
- 更强的安全性:通过对载荷内容进行加密,确保敏感信息不被泄露
- 合规性支持:满足 GDPR、HIPAA 等数据保护法规的要求
- 适用场景明确:特别适合处理敏感数据传输和高安全要求的环境
- 集成便利:在 Spring Boot 等现代框架中可以方便地集成和使用
然而,JWE
也带来了额外的复杂性和性能开销,因此在选择使用时需要根据具体的安全需求和性能要求进行权衡。对于包含敏感信息的令牌传输,JWE
是一个值得推荐的安全解决方案。
针对以上内容有任何疑问或者建议欢迎留言讨论。
创作不易,欢迎一键三连~~~