JWT令牌鉴权是一种基于令牌的身份验证机制,它使用JSON Web Token(JWT)来验证用户的身份。在使用SpringBoot-Vue框架开发应用时,可以使用JWT令牌鉴权来保护接口的访问,并实现用户的身份验证和权限控制。
以下是基于SpringBoot-Vue框架使用JWT令牌鉴权的步骤:
引入依赖:
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.1</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.3.7</version>
</dependency>
生成JWT令牌:
在用户登录成功后,服务器生成一个JWT令牌,其中包含用户的身份信息和其他相关信息。可以使用Java的JWT库(如jjwt)来生成JWT令牌。
import cn.hutool.core.util.StrUtil;
import com.computer.pojo.User;
import com.computer.service.UserService;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import java.util.Date;
import java.util.Map;
@Slf4j
@Component
public class JwtTokenUtils {
private static String signKey = "heima"; // 加密规则
private static Long expire = 43200000L; // 有效期
private static UserService staticUserService;
@Resource
private UserService userService;
@PostConstruct
public void setUserService(){
staticUserService = userService;
}
/**
* 生成JWT令牌
* @param claims JWT第二部分负载 payload 中存储的内容
* @return
*/
public static String generateJwt(Map<String, Object> claims){
String jwt = Jwts.builder()
.addClaims(claims)
.signWith(SignatureAlgorithm.HS256, signKey)
.setExpiration(new Date(System.currentTimeMillis() + expire))
.compact();
return jwt;
}
/**
* 解析JWT令牌
* @param jwt JWT令牌
* @return JWT第二部分负载 payload 中存储的内容
*/
public static Claims parseJWT(String jwt){
Claims claims = Jwts.parser()
.setSigningKey(signKey)
.parseClaimsJws(jwt)
.getBody();
return claims;
}
/**
* 获取当前登录用户信息
* @return
*/
public static User getCurrentUser(){
String token = null;
try {
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
token = request.getHeader("token");
if (StrUtil.isBlank(token)){
// token为空,去参数中查找
token = request.getParameter("token");
}
if (StrUtil.isBlank(token)){
log.error("获取当前登录的用户信息失败, token={}",token);
return null;
}
// 解析token,获取用户id
Integer nameId = (Integer) parseJWT(token).get("id");
return staticUserService.findById(nameId);
} catch (Exception e) {
log.error("获取当前登录的用户信息失败, token={}",token, e);
return null;
}
}
}
将JWT令牌返回给前端:
将生成的JWT令牌返回给前端,前端可以将其保存在本地。
localStorage.setItem("user", JSON.stringify(res.data));
前端发起请求时携带JWT令牌:
前端在每次请求接口时,在请求头中携带JWT令牌。可以使用axios等AJAX库来发送带有JWT令牌的请求。
const user = localStorage.getItem("user");
if (user){
config.headers['token'] = JSON.parse(user).token; // 设置请求头
}
后端验证JWT令牌:
后端在接收到请求时,需要验证JWT令牌的有效性。可以编写一个拦截器或过滤器来实现JWT令牌的验证。验证的过程包括解析JWT令牌、验证签名和验证令牌的相关信息(如过期时间)。
import cn.hutool.core.util.StrUtil;
import com.computer.pojo.User;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
@Slf4j
@Component
public class JwtInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
// 1、获取token
String token = request.getHeader("token");
if (StrUtil.isBlank(token)){
// token为空,去参数中查找
token = request.getParameter("token");
}
// 2、开始认证
if (StrUtil.isBlank(token)){
throw new CustomException("无token,请重新登录");
}
// 获取token中的adminID
User user;
try {
user = JwtTokenUtils.getCurrentUser();
} catch (Exception e) {
String errMsg = "token验证失败,请重新登录";
log.error(errMsg + ",token=" + token, e);
throw new CustomException(errMsg);
}
if (user == null){
throw new CustomException("用户不存在。请重新登录");
}
return true;
}
}
自定义拦截器
public void addInterceptors(InterceptorRegistry registry) {
// 拦截使用请求
registry.addInterceptor(jwtInterceptor).addPathPatterns("/api/**")
// 排除登录、注册
.excludePathPatterns("/api/register")
.excludePathPatterns("/api/login");
}
鉴权结果返回给前端:
在JWT令牌验证成功后,后端可以将鉴权结果返回给前端。可以返回用户信息或鉴权成功的状态码,前端可以统一处理返回结果。
// response 拦截器
// 可以在接口响应后统一处理结果
request.interceptors.response.use(
response => {
// response.data即为后端返回的Result
let res = response.data;
// 兼容服务端返回的字符串数据
if (typeof res === 'string'){
res = res ? JSON.parse(res) : res
}
return res;
}, error => {
console.log('err' + error) // for debug
return Promise.reject(error)
}
)