您现在的位置是:首页 >技术教程 >springboot使用shiro验证登录并用JWT生成token,并支持验证token刷新,token里存放用户名、部门、用户id、部门id,放在拦截器里面,封装成java工具类网站首页技术教程
springboot使用shiro验证登录并用JWT生成token,并支持验证token刷新,token里存放用户名、部门、用户id、部门id,放在拦截器里面,封装成java工具类
简介springboot使用shiro验证登录并用JWT生成token,并支持验证token刷新,token里存放用户名、部门、用户id、部门id,放在拦截器里面,封装成java工具类
JWT 工具类 (JwtUtils.java)
import io.jsonwebtoken.*;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
public class JwtUtils {
// JWT 密钥
private static final String SECRET_KEY = "your-secret-key";
// JWT 过期时间(单位:毫秒)
private static final long EXPIRATION_TIME = 86400000; // 24 小时
// Token 刷新时间(单位:毫秒)
private static final long REFRESH_TIME = 3600000; // 1 小时
// 生成 Token(包含用户名、部门、用户ID、部门ID)
public static String generateToken(String username, String dept, String userId, String deptId) {
Map<String, Object> claims = new HashMap<>();
claims.put("dept", dept);
claims.put("userId", userId);
claims.put("deptId", deptId);
return Jwts.builder()
.setClaims(claims)
.setSubject(username)
.setIssuedAt(new Date())
.setExpiration(new Date(System.currentTimeMillis() + EXPIRATION_MS))
.signWith(SignatureAlgorithm.HS256, SECRET_KEY)
.compact();
}
// 解析 Token
public static Claims parseToken(String token) {
return Jwts.parser()
.setSigningKey(SECRET_KEY)
.parseClaimsJws(token)
.getBody();
}
// 验证 Token 有效性
public static boolean validateToken(String token) {
try {
parseToken(token);
return true;
} catch (ExpiredJwtException | SignatureException | MalformedJwtException e) {
return false;
}
}
/**
* 刷新 Token
*
* @param token 旧的 Token
* @return 新的 Token
*/
public static String refreshToken(String token) {
String username = getUsernameFromToken(token);
return generateToken(username);
}
}
拦截器:JwtInterceptor
在拦截器中验证 JWT Token 的有效性,并支持 Token 刷新。
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class JwtInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// 从请求头中获取 Token
String token = request.getHeader("Authorization");
// 如果 Token 不存在,返回未授权错误
if (token == null || token.isEmpty()) {
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
response.getWriter().write("Unauthorized: Token is missing");
return false;
}
// 验证 Token 是否有效
if (!JwtUtils.validateToken(token)) {
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
response.getWriter().write("Unauthorized: Invalid token");
return false;
}
// 检查 Token 是否需要刷新
if (JwtUtils.isTokenNeedRefresh(token)) {
// 生成新的 Token
String newToken = JwtUtils.refreshToken(token);
// 将新的 Token 添加到响应头中
response.setHeader("Authorization", newToken);
}
// 将用户名设置到 Shiro 的 Subject 中
String username = JwtUtils.getUsernameFromToken(token);
Subject currentUser = SecurityUtils.getSubject();
if (!currentUser.isAuthenticated()) {
currentUser.login(new JwtToken(token));
}
// 如果 Token 有效,继续执行请求
return true;
}
}
自定义 Token:JwtToken
实现 Shiro 的 AuthenticationToken 接口,用于封装 JWT Token。
import org.apache.shiro.authc.AuthenticationToken;
public class JwtToken implements AuthenticationToken {
private final String token;
public JwtToken(String token) {
this.token = token;
}
@Override
public Object getPrincipal() {
return token;
}
@Override
public Object getCredentials() {
return token;
}
}
配置拦截器
在 Spring Boot 中配置拦截器。
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 WebConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 注册拦截器,并设置拦截路径
registry.addInterceptor(new JwtInterceptor())
.addPathPatterns("/**") // 拦截所有路径
.excludePathPatterns("/login"); // 排除登录路径
}
}
登录接口
在控制器中实现登录接口,生成 JWT Token 并返回给客户端。
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class LoginController {
@PostMapping("/login")
public String login(@RequestParam String username, @RequestParam String password) {
// 使用 Shiro 进行登录验证
if (ShiroUtils.login(username, password)) {
// 生成 JWT Token
String token = JwtUtils.generateToken(username);
return "Login successful! Token: " + token;
} else {
return "Login failed!";
}
}
}
Shiro 工具类:ShiroUtils
封装 Shiro 的常用操作。
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
public class ShiroUtils {
/**
* 用户登录验证
*
* @param username 用户名
* @param password 密码
* @return 登录成功返回 true,否则返回 false
*/
public static boolean login(String username, String password) {
Subject currentUser = SecurityUtils.getSubject();
UsernamePasswordToken token = new UsernamePasswordToken(username, password);
try {
// 执行登录
currentUser.login(token);
return true;
} catch (AuthenticationException e) {
// 登录失败
return false;
}
}
}
风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。





QT多线程的5种用法,通过使用线程解决UI主界面的耗时操作代码,防止界面卡死。...
U8W/U8W-Mini使用与常见问题解决
stm32使用HAL库配置串口中断收发数据(保姆级教程)
分享几个国内免费的ChatGPT镜像网址(亲测有效)
Allegro16.6差分等长设置及走线总结