package com.xly.erp.common.security; import io.jsonwebtoken.Claims; import io.jsonwebtoken.Jwts; import io.jsonwebtoken.security.Keys; import java.nio.charset.StandardCharsets; import java.util.Date; import javax.crypto.SecretKey; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; /** * JWT 工具(docs/04 § 1.7)。 * *

REQ-USR-001 T3:签发 / 解析含 sUserName + sUserType claim 的无状态 token; * 密钥取自 config-vars.yaml secrets.jwt_secret(经 application.yml 注入),禁止硬编码。

*/ @Component public class JwtUtil { /** claim:用户名。 */ public static final String CLAIM_USER_NAME = "sUserName"; /** claim:用户类型。 */ public static final String CLAIM_USER_TYPE = "sUserType"; private final SecretKey secretKey; private final long expireMillis; public JwtUtil(@Value("${jwt.secret}") String secret, @Value("${jwt.expire-millis}") long expireMillis) { this.secretKey = Keys.hmacShaKeyFor(secret.getBytes(StandardCharsets.UTF_8)); this.expireMillis = expireMillis; } /** * 签发 token,主体为用户名,并附带用户类型 claim。 */ public String generateToken(String userName, String userType) { Date now = new Date(); Date expiry = new Date(now.getTime() + expireMillis); return Jwts.builder() .subject(userName) .claim(CLAIM_USER_NAME, userName) .claim(CLAIM_USER_TYPE, userType) .issuedAt(now) .expiration(expiry) .signWith(secretKey) .compact(); } /** * 校验 token 签名与有效期;非法 / 过期返回 false。 */ public boolean validateToken(String token) { try { parseClaims(token); return true; } catch (RuntimeException ex) { return false; } } public String getUserName(String token) { return parseClaims(token).get(CLAIM_USER_NAME, String.class); } public String getUserType(String token) { return parseClaims(token).get(CLAIM_USER_TYPE, String.class); } private Claims parseClaims(String token) { return Jwts.parser() .verifyWith(secretKey) .build() .parseSignedClaims(token) .getPayload(); } }