bug
Codex Assistant
2025-11-05 3714621173c606c4c58439ed8941100ce9ddea14
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
package com.rongyichuang.auth.util;
 
import io.jsonwebtoken.*;
import io.jsonwebtoken.security.Keys;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
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;
 
/**
 * JWT工具类
 */
@Component
public class JwtUtil {
 
    private static final Logger logger = LoggerFactory.getLogger(JwtUtil.class);
 
    @Value("${app.jwt.secret}")
    private String jwtSecret;
 
    @Value("${app.jwt.expiration:86400000}") // 默认24小时
    private long jwtExpiration;
 
    /**
     * 生成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 = getSigningKey();
 
        JwtBuilder builder = Jwts.builder()
                .setSubject(userId.toString())
                .setIssuedAt(now)
                .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);
        }
    }
 
    /**
     * 从token中获取用户ID
     */
    public Long getUserIdFromToken(String token) {
        Claims claims = getClaimsFromToken(token);
        return Long.parseLong(claims.getSubject());
    }
 
    /**
     * 从token中获取手机号
     */
    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是否有效
     */
    public boolean validateToken(String token) {
        try {
            getClaimsFromToken(token);
            return true;
        } catch (JwtException | IllegalArgumentException e) {
            logger.error("JWT token验证失败: {}", e.getMessage());
            return false;
        }
    }
 
    /**
     * 检查token是否过期
     */
    public boolean isTokenExpired(String token) {
        try {
            Claims claims = getClaimsFromToken(token);
            return claims.getExpiration().before(new Date());
        } catch (JwtException | IllegalArgumentException e) {
            return true;
        }
    }
 
    /**
     * 从token中解析Claims
     */
    private Claims getClaimsFromToken(String token) {
        SecretKey key = getSigningKey();
        return Jwts.parserBuilder()
                .setSigningKey(key)
                .build()
                .parseClaimsJws(token)
                .getBody();
    }
}