目前只写了后端方面的,马上在补充一下前端的吧
1. 后端处理过程
依赖
<!-- JJWT 核心 API -->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
<version>0.11.5</version>
</dependency>
<!-- JJWT 实现类(运行时依赖) -->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
<version>0.11.5</version>
<scope>runtime</scope>
</dependency>
<!-- JSON 序列化(Jackson) -->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId>
<version>0.11.5</version>
<scope>runtime</scope>
</dependency>
添加jwt配置文件
# JWT 核心配置(必须添加)
jwt:
# 密钥(必须是32位以上字符串,可随便写,生产环境要随机生成)
secret: abcdefghijklmnopqrstuvwxyz1234567890abcdef
# 过期时间(秒):10小时 = 36000秒
expire-time: 36000
补充*可选:关闭mybaits打印logo
mybatis-plus:
global-config:
banner: false # 关闭 MyBatis-Plus 启动 Logo
目录结构

jwtutil.java
package com.example.wms001.common;
import io.jsonwebtoken.*;
import io.jsonwebtoken.security.Keys;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import javax.crypto.SecretKey;
import java.util.Date;
import java.util.Map;
@Component
public class JwtUtil {
// 从配置文件读取密钥(application.yml 配置不变)
@Value("${jwt.secret}")
private String secret;
// Token过期时间(秒)
@Value("${jwt.expire-time}")
private Long expireTime;
// 生成密钥
private SecretKey getSecretKey() {
return Keys.hmacShaKeyFor(secret.getBytes());
}
// 生成Token(逻辑不变)
public String generateToken(String userId, Map<String, Object> claims) {
Date now = new Date();
Date expireDate = new Date(now.getTime() + expireTime * 1000);
return Jwts.builder()
.setClaims(claims)
.setSubject(userId)
.setIssuedAt(now)
.setExpiration(expireDate)
.signWith(getSecretKey(), SignatureAlgorithm.HS256)
.compact();
}
// 解析Token(逻辑不变)
public Claims parseToken(String token) {
try {
return Jwts.parserBuilder()
.setSigningKey(getSecretKey())
.build()
.parseClaimsJws(token)
.getBody();
} catch (ExpiredJwtException e) {
throw new RuntimeException("Token已过期");
} catch (JwtException e) {
throw new RuntimeException("Token无效");
}
}
// 获取用户ID(逻辑不变)
public String getUserIdFromToken(String token) {
return parseToken(token).getSubject();
}
// 验证Token(逻辑不变)
public boolean validateToken(String token) {
try {
parseToken(token);
return true;
} catch (Exception e) {
return false;
}
}
}
jwt拦截器Jwtinterceptr.java
package com.example.wms001.common;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import jakarta.servlet.http.HttpServletRequest; // 关键:jakarta而非javax
import jakarta.servlet.http.HttpServletResponse;
@Component
public class JwtInterceptor implements HandlerInterceptor {
@Autowired
private JwtUtil jwtUtil; // 注入common包的JwtUtil
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// 排除登录接口
String requestURI = request.getRequestURI();
if (requestURI.contains("/user/login")) {
return true;
}
// 获取Token
String token = request.getHeader("Authorization");
if (token == null || !token.startsWith("Bearer ")) {
throw new RuntimeException("请先登录");
}
token = token.replace("Bearer ", "");
// 验证Token
if (!jwtUtil.validateToken(token)) {
throw new RuntimeException("Token无效或已过期");
}
// 存入用户ID到请求域
String userId = jwtUtil.getUserIdFromToken(token);
request.setAttribute("userId", userId);
return true;
}
}
配置文件
package com.example.wms001.common;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Autowired
private JwtInterceptor jwtInterceptor; // 注入common包的拦截器
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(jwtInterceptor)
.addPathPatterns("/**")
.excludePathPatterns("/user/login");
}
}