refactor: 重构实体类并添加Lombok注解 docs: 更新数据库表结构文档 style: 清理无用代码并优化格式 fix: 修复用户详情服务中的联系方式更新方法 build: 更新pom.xml配置并添加Lombok插件 test: 添加用户登录测试用例 chore: 添加开发和生产环境配置文件
120 lines
3.4 KiB
Java
120 lines
3.4 KiB
Java
package com.qf.backend.util;
|
||
|
||
import java.nio.charset.StandardCharsets;
|
||
import java.util.Date;
|
||
import java.util.HashMap;
|
||
import java.util.Map;
|
||
import java.util.function.Function;
|
||
|
||
import javax.crypto.SecretKey;
|
||
|
||
import org.springframework.beans.factory.annotation.Value;
|
||
import org.springframework.security.core.userdetails.UserDetails;
|
||
import org.springframework.stereotype.Component;
|
||
|
||
import io.jsonwebtoken.Claims;
|
||
import io.jsonwebtoken.Jwts;
|
||
import io.jsonwebtoken.security.Keys;
|
||
|
||
/**
|
||
* JWT工具类,用于生成和验证token(JJWT 0.12.x 版本)
|
||
* 支持 Java 17+ 和 Jakarta EE(Spring Boot 3.x)
|
||
*/
|
||
@Component
|
||
public class JwtUtils {
|
||
|
||
@Value("${jwt.secret:default_secret_key_for_development}")
|
||
private String secret;
|
||
|
||
@Value("${jwt.expiration:3600000}")
|
||
private long expiration;
|
||
|
||
@Value("${jwt.token-prefix:Bearer}")
|
||
private String tokenPrefix;
|
||
|
||
/**
|
||
* 获取签名密钥
|
||
*/
|
||
private SecretKey getSignInKey() {
|
||
byte[] keyBytes = secret.getBytes(StandardCharsets.UTF_8);
|
||
return Keys.hmacShaKeyFor(keyBytes);
|
||
}
|
||
|
||
/**
|
||
* 从token中获取用户名
|
||
*/
|
||
public String getUsernameFromToken(String token) {
|
||
return getClaimFromToken(token, Claims::getSubject);
|
||
}
|
||
|
||
/**
|
||
* 从token中获取过期时间
|
||
*/
|
||
public Date getExpirationDateFromToken(String token) {
|
||
return getClaimFromToken(token, Claims::getExpiration);
|
||
}
|
||
|
||
/**
|
||
* 从token中获取指定的claim
|
||
*/
|
||
public <T> T getClaimFromToken(String token, Function<Claims, T> claimsResolver) {
|
||
final Claims claims = getAllClaimsFromToken(token);
|
||
return claimsResolver.apply(claims);
|
||
}
|
||
|
||
/**
|
||
* 获取token中的所有claims
|
||
*/
|
||
private Claims getAllClaimsFromToken(String token) {
|
||
return Jwts.parser()
|
||
.verifyWith(getSignInKey())
|
||
.build()
|
||
.parseSignedClaims(token)
|
||
.getPayload();
|
||
}
|
||
|
||
/**
|
||
* 检查token是否过期
|
||
*/
|
||
private Boolean isTokenExpired(String token) {
|
||
final Date expiration = getExpirationDateFromToken(token);
|
||
return expiration.before(new Date());
|
||
}
|
||
|
||
/**
|
||
* 生成token
|
||
*/
|
||
public String generateToken(UserDetails userDetails) {
|
||
Map<String, Object> claims = new HashMap<>();
|
||
claims.put("authorities", userDetails.getAuthorities());
|
||
return doGenerateToken(claims, userDetails.getUsername());
|
||
}
|
||
|
||
/**
|
||
* 生成token的核心方法
|
||
*/
|
||
private String doGenerateToken(Map<String, Object> claims, String subject) {
|
||
return Jwts.builder()
|
||
.claims(claims) // 使用新的 claims() 方法
|
||
.subject(subject) // 使用新的 subject() 方法
|
||
.issuedAt(new Date(System.currentTimeMillis()))
|
||
.expiration(new Date(System.currentTimeMillis() + expiration)) // 使用新的 expiration() 方法
|
||
.signWith(getSignInKey(), Jwts.SIG.HS256) // 使用新的签名方式
|
||
.compact();
|
||
}
|
||
|
||
/**
|
||
* 验证token
|
||
*/
|
||
public Boolean validateToken(String token, UserDetails userDetails) {
|
||
final String username = getUsernameFromToken(token);
|
||
return (username.equals(userDetails.getUsername()) && !isTokenExpired(token));
|
||
}
|
||
|
||
/**
|
||
* 获取token前缀
|
||
*/
|
||
public String getTokenPrefix() {
|
||
return tokenPrefix;
|
||
}
|
||
} |