【经验分享】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 是一个值得推荐的安全解决方案。

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

相关推荐
我命由我123453 小时前
Photoshop - Photoshop 工具栏(2)矩形框选工具
经验分享·笔记·学习·ui·photoshop·ps·美工
青草地溪水旁7 小时前
EPOLLONESHOT事件类型和ET模式有什么区别?
服务器·网络·c++·epoll
青草地溪水旁8 小时前
tcpdump调试
网络·测试工具·tcpdump
云手机掌柜9 小时前
技术深度解析:指纹云手机如何通过设备指纹隔离技术重塑多账号安全管理
大数据·服务器·安全·智能手机·矩阵·云计算
kebeiovo9 小时前
muduo网络库事件驱动模型的实现与架构
网络·架构
德迅云安全杨德俊11 小时前
SCDN-保护网站安全的有效方案
网络·安全·web安全·ddos
YongCheng_Liang11 小时前
网络工程师笔记8-OSPF协议
运维·网络·网络协议
BossFriday12 小时前
【手撸IM】高性能HTTP API服务设计与实现
网络·网络协议·http
北京耐用通信13 小时前
耐达讯自动化Modbus RTU转Profibus,让电磁阀连接从此与众不同!
网络·人工智能·网络协议·网络安全·自动化