| | |
| | | import org.springframework.stereotype.Component; |
| | | |
| | | import javax.crypto.SecretKey; |
| | | import javax.crypto.spec.SecretKeySpec; |
| | | import java.nio.charset.StandardCharsets; |
| | | import java.security.MessageDigest; |
| | | import java.util.Date; |
| | | |
| | | /** |
| | |
| | | private long jwtExpiration; |
| | | |
| | | /** |
| | | * 生成JWT token |
| | | * 生成JWT token(旧版本,保持兼容性) |
| | | */ |
| | | public String generateToken(Long userId, String phone) { |
| | | return generateToken(userId, phone, null); |
| | | } |
| | | |
| | | /** |
| | | * 生成JWT token(新版本,支持wxopenid) |
| | | */ |
| | | public String generateToken(Long userId, String phone, String wxopenid) { |
| | | Date now = new Date(); |
| | | Date expiryDate = new Date(now.getTime() + jwtExpiration); |
| | | |
| | | SecretKey key = Keys.hmacShaKeyFor(jwtSecret.getBytes()); |
| | | SecretKey key = getSigningKey(); |
| | | |
| | | return Jwts.builder() |
| | | JwtBuilder builder = Jwts.builder() |
| | | .setSubject(userId.toString()) |
| | | .claim("phone", phone) |
| | | .setIssuedAt(now) |
| | | .setExpiration(expiryDate) |
| | | .signWith(key, SignatureAlgorithm.HS256) |
| | | .compact(); |
| | | .setExpiration(expiryDate); |
| | | |
| | | // 只有当phone不为null时才添加phone claim |
| | | if (phone != null) { |
| | | builder.claim("phone", phone); |
| | | } |
| | | |
| | | // 只有当wxopenid不为null时才添加wxopenid claim |
| | | if (wxopenid != null) { |
| | | builder.claim("wxopenid", wxopenid); |
| | | } |
| | | |
| | | return builder.signWith(key, SignatureAlgorithm.HS256).compact(); |
| | | } |
| | | |
| | | /** |
| | | * 根据配置的密钥生成满足 HMAC-SHA 要求的签名密钥: |
| | | * - 若明文密钥长度不足 256 bit,使用 SHA-256 衍生为 256-bit |
| | | * - 保持对现有 app.jwt.secret 的兼容,不修改配置键名或其它逻辑 |
| | | */ |
| | | private SecretKey getSigningKey() { |
| | | try { |
| | | byte[] keyBytes = jwtSecret.getBytes(StandardCharsets.UTF_8); |
| | | if (keyBytes.length < 32) { |
| | | MessageDigest digest = MessageDigest.getInstance("SHA-256"); |
| | | keyBytes = digest.digest(keyBytes); |
| | | } |
| | | if (keyBytes.length < 32) { |
| | | byte[] padded = new byte[32]; |
| | | System.arraycopy(keyBytes, 0, padded, 0, Math.min(keyBytes.length, 32)); |
| | | keyBytes = padded; |
| | | } |
| | | return new SecretKeySpec(keyBytes, "HmacSHA256"); |
| | | } catch (Exception e) { |
| | | throw new RuntimeException("初始化JWT签名密钥失败", e); |
| | | } |
| | | } |
| | | |
| | | /** |
| | |
| | | public String getPhoneFromToken(String token) { |
| | | Claims claims = getClaimsFromToken(token); |
| | | return claims.get("phone", String.class); |
| | | } |
| | | |
| | | /** |
| | | * 从token中获取微信openid |
| | | */ |
| | | public String getWxOpenidFromToken(String token) { |
| | | Claims claims = getClaimsFromToken(token); |
| | | return claims.get("wxopenid", String.class); |
| | | } |
| | | |
| | | /** |
| | |
| | | * 从token中解析Claims |
| | | */ |
| | | private Claims getClaimsFromToken(String token) { |
| | | SecretKey key = Keys.hmacShaKeyFor(jwtSecret.getBytes()); |
| | | SecretKey key = getSigningKey(); |
| | | return Jwts.parserBuilder() |
| | | .setSigningKey(key) |
| | | .build() |