package com.trafficaudit.security.utils;
|
|
import io.jsonwebtoken.Claims;
|
import io.jsonwebtoken.Jwts;
|
import io.jsonwebtoken.SignatureAlgorithm;
|
import io.jsonwebtoken.impl.TextCodec;
|
import org.slf4j.Logger;
|
import org.slf4j.LoggerFactory;
|
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.stereotype.Component;
|
|
import java.nio.charset.StandardCharsets;
|
import java.util.Date;
|
import java.util.HashMap;
|
import java.util.Map;
|
|
@Component
|
public class JwtUtils {
|
|
private static final Logger log = LoggerFactory.getLogger(JwtUtils.class);
|
|
@Value("${jwt.secret}")
|
private String secret;
|
|
@Value("${jwt.expiration}")
|
private Long expiration;
|
|
/**
|
* 签名密钥字节:jjwt 0.9.x 默认把 secret 当 Base64 解码,若配置成中文等非法 Base64 会在登录时抛
|
* ArrayIndexOutOfBoundsException,表现为「登录接口 500」。这里做兜底:能按 Base64 解码就用解码结果
|
* (与历史 token 兼容),否则按 UTF-8 字节处理,并把提示打到日志里。
|
*/
|
private byte[] secretKeyBytes() {
|
try {
|
return TextCodec.BASE64.decode(secret);
|
} catch (Exception e) {
|
log.warn("jwt.secret 不是合法的 Base64 字符串,已按 UTF-8 字节作为签名密钥;建议改成 32 位随机十六进制串。");
|
return secret.getBytes(StandardCharsets.UTF_8);
|
}
|
}
|
|
public String generateToken(String username) {
|
Map<String, Object> claims = new HashMap<>();
|
claims.put("username", username);
|
return Jwts.builder()
|
.setClaims(claims)
|
.setSubject(username)
|
.setIssuedAt(new Date())
|
.setExpiration(new Date(System.currentTimeMillis() + expiration))
|
.signWith(SignatureAlgorithm.HS256, secretKeyBytes())
|
.compact();
|
}
|
|
public String getUsernameFromToken(String token) {
|
Claims claims = Jwts.parser().setSigningKey(secretKeyBytes())
|
.parseClaimsJws(token).getBody();
|
return claims.getSubject();
|
}
|
|
public boolean validateToken(String token) {
|
try {
|
Jwts.parser().setSigningKey(secretKeyBytes()).parseClaimsJws(token);
|
return true;
|
} catch (Exception e) {
|
return false;
|
}
|
}
|
|
/** 从 Authorization: Bearer xxx 请求头解析用户名;无效返回 null */
|
public String resolveUsername(String authorizationHeader) {
|
if (authorizationHeader == null || !authorizationHeader.startsWith("Bearer ")) {
|
return null;
|
}
|
try {
|
return getUsernameFromToken(authorizationHeader.substring(7));
|
} catch (Exception e) {
|
return null;
|
}
|
}
|
}
|