Springboot3 + vue3实现jwt登录鉴权
为什么要做鉴权?
因为管理系统的数据是敏感的,隐私的,而且一般每隔角色的权限是不同的,所以必须在数据的增删改查操作的时候对访问的用户做权限验证.
什么是JWT?
JSON Web Token(JWT) 是一种开放标准(RFC 7519),用于在网络应用间安全地传输信息.它以紧凑且自包含的方式,通过JSON对象在各方之间传递经过验证的信息.
JWT由三部分组成,用.分隔:
Header(头部):包含算法(HMAC SHA256 或 RSA)和令牌类型(固定位 JWT).
1 2 3 4
| { "alg": "HS256", "typ": "JWT" }
|
Payload(负载): 携带声明(如用户身份,权限,有效期等),分为三类:
- Registered claims (预定义字段,如
exp 过期时间,iss 签发者).
- Public claims (公开自定义字段,需避免冲突).
- Private claims (私有字段,双方协商)
1 2 3 4 5
| { "sub" : "1234567890", "name": "John Doe", "admin": true }
|
- Signature(签名) : 对头部和负载的签名,防止数据篡改.
集成JWT
1 2 3 4 5
| <dependency> <groupId>com.auth0</groupId> <artifactId>java-jwt</artifactId> <version>4.3.0</version> </dependency>
|
生成Token
1 2 3 4 5 6 7 8
|
public static String createToken(String data,String sign) { return JWT.create().withAudience(data) .withExpiresAt(DateUtil.offsetDay(new Date(),1)) .sign(Algorithm,HMAC256(sign)); }
|
AdminService的login方法
1 2 3
| String token = TokenUtils.createToken(dbAdmin.getId() + "-" + "ADMIN", dbAdmin.getPassword()); dbAdmin.setToken(token);
|
Token的格式

1
| eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJhdWQiOiIxLUFETUlOIiwiZXhwIjoxNzQxMTUzNzEzfQ.6xn-9aIovSwd46p77sD9PR9RVcykdRPrDWlkgYWRm0A
|
JWT拦截器
对所有接口的请求做一个验证
先是拦住所有的请求:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| @Configuration public class WebConfig implements WebMvcConfigurer { @Resource private JWTInterceptor jwtInterceptor; @Override public void addInterceptors(InterceptorRegistry registery) { registry.addInterceptor(jwtInterceptor).addPathPatterns("/**") .excludePathPatterns("/") .excludePathPatterns("/login","/register","/files/**","/role/selectAll"); } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68
| package com.yjy.Interceptor;
import cn.hutool.core.util.StrUtil; import com.auth0.jwt.JWT; import com.auth0.jwt.JWTVerifier; import com.auth0.jwt.algorithms.Algorithm; import com.yjy.entity.Account; import com.yjy.exception.CustomerException; import com.yjy.service.AdminService; import com.yjy.service.UserService; import jakarta.annotation.Resource; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import org.springframework.web.servlet.HandlerInterceptor;
public class JWTInterceptor implements HandlerInterceptor {
@Resource AdminService adminService; @Resource UserService userService;
@Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { String token = request.getHeader("token"); if(StrUtil.isEmpty(token)) { token = request.getParameter("token"); } if(StrUtil.isBlank(token)) { throw new CustomerException("401","您无权限操作"); } Account account = null; try {
String audience = JWT.decode(token).getAudience().get(0); String[] split = audience.split("-"); String userId = split[0]; String role = split[1]; if("ADMIN".equals(role)) { account = adminService.selectById(userId); }else if("USER".equals(role)){ account = userService.selectById(userId); }
}catch(Exception e){ throw new CustomerException("401","您无权限操作"); } if(account == null){ throw new CustomerException("401","您无权限操作"); }
try{ JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(account.getPassword())).build(); jwtVerifier.verify(token); }catch (Exception e){ throw new CustomerException("401","您无权限操作"); } return true; } }
|
配置类
1 2 3 4 5 6 7 8 9 10 11 12
| package com.yjy.Interceptor;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration;
@Configuration public class InterceptorConfig { @Bean public JWTInterceptor jwtInterceptor() { return new JWTInterceptor(); } }
|
出现401错误,您无权限访问数据怎么办?

在vue的request.js的拦截器里面加上统一的请求头token
1 2 3 4 5 6 7 8
| request.interceptors.request.use(config => { config.headers['Content-Type']='application/json;charset=utf-8'; let user = JSON.parse(localStorage.getItem('code2025_user') || '{}'); config.headers['token'] = user.token return config },error => { return Promise.reject(error) });
|
看网络请求:

request.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69
| import axios from "axios"; import {ElMessage} from "element-plus"; import router from "@/router/index.js";
const request = axios.create({ baseURL: 'http://localhost:9999', timeout: 30000 })
request.interceptors.request.use(config => { config.headers['Content-Type']='application/json;charset=utf-8'; let user = JSON.parse(localStorage.getItem('code2025_user') || '{}'); config.headers['token'] = user.token return config },error => { return Promise.reject(error) });
request.interceptors.response.use( response=>{ let res = response.data; if(typeof res === 'string'){ res = res?JSON.parse(res):res } if(res.code === '401'){ ElMessage.error(res.msg) router.push('/login') }else{ return res }
}, error => { if(error.response.status === 404){ ElMessage.error("未找到请求接口") }else if(error.response.status===500) { ElMessage.error("系统异常,请查看后端控制台报错") }else{ console.error(error.message) } return Promise.reject(error) } )
export default request
|
解析Token获取用户数据
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74
| package com.yjy.utils;
import cn.hutool.core.date.DateUtil; import cn.hutool.core.util.StrUtil; import com.auth0.jwt.JWT; import com.auth0.jwt.algorithms.Algorithm; import com.yjy.entity.Account; import com.yjy.service.AdminService; import com.yjy.service.UserService; import jakarta.annotation.PostConstruct; import jakarta.annotation.Resource; import jakarta.servlet.http.HttpServletRequest; import org.springframework.stereotype.Component; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes;
import java.util.Date;
@Component public class TokenUtils {
@Resource AdminService adminService;
@Resource UserService userService;
static AdminService staticAdminService; static UserService staticUserService;
@PostConstruct public void init(){ staticAdminService = adminService; staticUserService = userService; }
public static String createToken(String data,String sign) { return JWT.create().withAudience(data) .withExpiresAt(DateUtil.offsetDay(new Date(),1)) .sign(Algorithm.HMAC256(sign)); }
public static Account getCurrentUser(){ Account account = null; HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); String token = request.getHeader("token"); if(StrUtil.isBlank(token)){ token = request.getParameter("token"); } String audience = JWT.decode(token).getAudience().get(0); String[] split = audience.split("-"); String userId = split[0]; String role = split[1]; if("ADMIN".equals(role)) { return staticAdminService.selectById(userId); }else if("USER".equals(role)){ return staticUserService.selectById(userId); } return null;
} }
|
在service方法里面 获取当前的登录用户信息
1
| Account currentUser = TokenUtils.getCurrentUser();
|
Springboot3 + vue3实现jwt登录鉴权