直接上代码
1、首先配置一下token相关的参数
jwt:
user-secret-key: xxxxxx
user-ttl: 72 # 令牌有效期(小时)
这两个随便填都可以的
2、我是直接创建了一个工具类用于有关token的操作
import com.ahalif.gongzhonghao.properties.JwtProperties;
import io.jsonwebtoken.*;
import jakarta.servlet.http.HttpServletRequest;
import org.apache.http.HttpHeaders;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import java.util.Date;
/**
* JWT令牌工具类,用于生成、验证和刷新用户令牌
*/
@Component
public class UserTokenUtils {
private final JwtProperties jwtProperties;
private static final Logger logger = LoggerFactory.getLogger(UserTokenUtils.class);
// JWT签名算法
private static final SignatureAlgorithm SIGNATURE_ALGORITHM = SignatureAlgorithm.HS256;
@Autowired
public UserTokenUtils(JwtProperties jwtProperties) {
this.jwtProperties = jwtProperties;
// 检查密钥是否为空
if (jwtProperties.getUserSecretKey() == null || jwtProperties.getUserSecretKey().isEmpty()) {
logger.error("JWT密钥未配置!请检查application.properties中的jwt.user-secret-key配置");
throw new IllegalArgumentException("JWT密钥不能为空");
}
}
/**
* 生成JWT令牌
* @param personId 用户ID
* @return JWT令牌
*/
public String generateToken(String personId) {
long expirationTime = jwtProperties.getUserTtl() * 60 * 60 * 1000; // 转换为毫秒,默认72小时
return Jwts.builder()
.setSubject(personId)
.setIssuedAt(new Date())
.setExpiration(new Date(System.currentTimeMillis() + expirationTime))
.signWith(SIGNATURE_ALGORITHM, jwtProperties.getUserSecretKey())
.compact();
}
/**
* 验证JWT令牌
* @param token JWT令牌
* @return 解析后的JWT声明
* @throws JwtException 令牌验证失败时抛出异常
*/
public Claims validateToken(String token) throws JwtException {
return Jwts.parser()
.setSigningKey(jwtProperties.getUserSecretKey())
.parseClaimsJws(token)
.getBody();
}
/**
* 刷新JWT令牌(延长有效期)
* @param token 原始JWT令牌
* @return 刷新后的JWT令牌
* @throws JwtException 令牌验证失败时抛出异常
*/
public String refreshToken(String token) throws JwtException {
Claims claims = validateToken(token);
return generateToken(claims.getSubject());
}
/**
* 从令牌中获取用户ID
* @param token JWT令牌
* @return 用户ID
* @throws JwtException 令牌验证失败时抛出异常
*/
public String getPersonIdFromToken(String token) throws JwtException {
return validateToken(token).getSubject();
}
/**
* 从HTTP请求中提取JWT令牌
* @return 提取的JWT令牌,若请求中未包含令牌则返回null
*/
public String getTokenFromRequest() {
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
if (attributes != null) {
HttpServletRequest request = attributes.getRequest();
String authHeader = request.getHeader(HttpHeaders.AUTHORIZATION);
if (authHeader != null && authHeader.startsWith("Bearer ")) {
return authHeader.substring(7); // 提取"Bearer "后的令牌
}
}
return null; // 若未找到令牌,则返回null
}
}
3、相关的类
import com.alibaba.fastjson2.JSONObject;
import io.jsonwebtoken.JwtException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import java.io.IOException;
import java.io.PrintWriter;
/**
* JWT令牌拦截器,用于验证请求中的令牌
*/
@Component
public class JwtInterceptor implements HandlerInterceptor {
private static final Logger logger = LoggerFactory.getLogger(JwtInterceptor.class);
@Autowired
private UserTokenUtils userTokenUtils;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// 排除登录路径
if (request.getRequestURI().contains("/denglu")
||request.getRequestURI().contains("/add")
) {
return true;
}
// 从请求头中获取令牌
String token = request.getHeader("Authorization");
// 验证令牌
try {
if (token != null && token.startsWith("Bearer ")) {
token = token.substring(7); // 去掉"Bearer "前缀
// 验证令牌有效性
userTokenUtils.validateToken(token);
// 刷新令牌(延长有效期)
String refreshedToken = userTokenUtils.refreshToken(token);
response.setHeader("Authorization", "Bearer " + refreshedToken);
logger.info("令牌验证成功,路径: {}", request.getRequestURI());
return true;
} else {
// 没有提供令牌
logger.warn("缺少令牌,路径: {}", request.getRequestURI());
sendErrorResponse(response, "缺少令牌");
return false;
}
} catch (JwtException e) {
// 令牌验证失败
logger.error("无效的令牌,路径: {}", request.getRequestURI(), e);
sendErrorResponse(response, "无效的令牌");
return false;
}
}
private void sendErrorResponse(HttpServletResponse response, String message) throws IOException {
response.setContentType("application/json;charset=UTF-8");
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
Result<String> result = Result.error(message);
String jsonResult = JSONObject.toJSONString(result);
try (PrintWriter writer = response.getWriter()) {
writer.write(jsonResult);
writer.flush();
}
}
}
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
@Configuration
@ConfigurationProperties(prefix = "jwt")
public class JwtProperties {
private String userSecretKey;
private long userTtl = 72; // 默认72小时
public String getUserSecretKey() {
return userSecretKey;
}
public void setUserSecretKey(String userSecretKey) {
this.userSecretKey = userSecretKey;
}
public long getUserTtl() {
return userTtl;
}
public void setUserTtl(long userTtl) {
this.userTtl = userTtl;
}
}
最最最重要的,写完后启动类上要加注解
大概就是这样了,如有错误,请各位大佬指正