【经验分享】JWE 详解:比 JWT 更安全的令牌技术

简单介绍

传统 JWT 的工作原理

JWT (JSON Web Token) 是一种开放标准(RFC 7519),用于在各方之间安全地传输信息。传统的 JWT 主要包含三个部分:

  1. Header - 头部信息
  2. Payload - 载荷数据
  3. 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 的增强版本,在数据安全性方面提供了显著优势:

  1. 更强的安全性:通过对载荷内容进行加密,确保敏感信息不被泄露
  2. 合规性支持:满足 GDPR、HIPAA 等数据保护法规的要求
  3. 适用场景明确:特别适合处理敏感数据传输和高安全要求的环境
  4. 集成便利:在 Spring Boot 等现代框架中可以方便地集成和使用

然而,JWE 也带来了额外的复杂性和性能开销,因此在选择使用时需要根据具体的安全需求和性能要求进行权衡。对于包含敏感信息的令牌传输,JWE 是一个值得推荐的安全解决方案。

针对以上内容有任何疑问或者建议欢迎留言讨论。
创作不易,欢迎一键三连~~~

相关推荐
byte轻骑兵8 分钟前
【安全函数】C语言安全字符串函数详解:告别缓冲区溢出的噩梦
c语言·安全·面试
聚梦小课堂18 分钟前
2025.11.16 AI快讯
人工智能·安全·语言模型
Ctrl+S 之后39 分钟前
分布式数据库高可用架构设计与动态一致性优化实践经验分享
数据库·经验分享·分布式
老朱佩琪!43 分钟前
找工作经验分享
经验分享
金士镧(厦门)新材料有限公司44 分钟前
稀土氧化物:材料科技中的“隐形力量”
科技·安全·全文检索
侯小啾1 小时前
VMware-ubuntu网络配置
网络·ubuntu·智能路由器·vmware·虚拟机
Nimsolax1 小时前
Linux网络DNS与ICMP
linux·网络
01100001乄夵2 小时前
Android入门教程 - 第三章:Android布局全攻略
android·经验分享·笔记·学习方法·android期末学习
AI科技星2 小时前
引力编程时代:人类文明存续与升维
数据结构·人工智能·经验分享·算法·计算机视觉
ARoger_miu577 小时前
11月13号作业
网络·智能路由器