我的计算机设计大赛的项目需要用到JWT来进行用户身份验证,项目采用springboot技术,因为我没学过springSrcurity所以只能用原生的拦截器+JWT技术进行验证,我是跟着【SpringBoot整合JWT】这篇文章做的,老师讲的很详细跟着一步一步来也可以实现JWT身份验证,但是对于验证过程的整个流程是不太清楚的,不知道代码是怎么运行完成验证的,后面自己debug和测试了下,在这里分享给大家!
stpe1:拦截器拦截http请求
首先使用spring提供的拦截器拦截前端发送的http请求,写一个配置类继承WebMvcConfigurer,实现里面的addInterceptors方法,在方法里调用InterceptorRegistry对象的addInterceptor方法提添加要拦截的url和放行的url
/**
* 拦截器,拦截/yangsheng路径下的所有请求进行token身份验证,但是放行/yangsheng/login
*/
@Configuration
public class InterceptConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
//添加拦截器
registry.addInterceptor(new JWTInterceptor())
//拦截的路径 需要进行token验证的路径
.addPathPatterns("/yangsheng/**")
//放行的路径
.excludePathPatterns("/yangsheng/user/login")
.excludePathPatterns("/yangsheng/user/register");
}
}
step2:对请求头进行分析,并进行拦截
通过上述拦截器拦截下http请求后就要对请求头进行分析了,分析是否携带token,token是否过期,是否合法等等。
这里会用到一个我们自己写的JWTUtil工具类
package com.example.yangshengproject.utils;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTCreator;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;
import java.util.Calendar;
import java.util.Map;
/**
* JWT工具类
*
* @author zhangzuhao
* @version 1.0
* @date 2023/5/18 21:28
*/
public class JWTUtil {
/**
* 密钥要自己保管好
*/
private static String SECRET = "!Q@W#E$R";
/**
* 传入payload信息获取token
* @param map payload
* @return token
*/
public static String getToken(Map<String, String> map) {
JWTCreator.Builder builder = JWT.create();
//payload
map.forEach((k,v)->{
builder.withClaim(k,v);
});
Calendar instance = Calendar.getInstance();
instance.add(Calendar.DATE, 1); //默认1天过期
builder.withExpiresAt(instance.getTime());//指定令牌的过期时间
return builder.sign(Algorithm.HMAC256(SECRET));
}
/**
* 验证token 合法性
*/
public static DecodedJWT verify(String token) {
//如果有任何验证异常,此处都会抛出异常
return JWT.require(Algorithm.HMAC256(SECRET)).build().verify(token);
}
/**
* 获取token信息方法
*/
public static Map<String, Claim> getTokenInfo(String token) {
return JWT.require(Algorithm.HMAC256(SECRET)).build().verify(token).getClaims();
}
}
new一个JWTInterceptor类作为JWT拦截器,实现HandlerInterceptor,实现里面的preHandler方法,这个方法会返回一个boolean值如果为true就会执行下一拦截器直到没有拦截器可执行就进入业务代码,如果返回false会立马中这次请求务不往下执行。
方法中通过request.getHeader("token")获取到请求头中token的信息,接着通过JWTUtil的verify方法进行验证如果没有抛异常说明验证通过,返回true,否则抛出异常try catch后返回false。
import com.auth0.jwt.interfaces.DecodedJWT;
import com.example.yangshengproject.utils.JWTUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.servlet.HandlerInterceptor;
import java.util.HashMap;
@Slf4j
public class JWTInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
HashMap<String, String> map=new HashMap<>();
//从http请求头获取token
String token = request.getHeader("token");
try {
//如果验证成功放行请求
DecodedJWT verify = JWTUtil.verify(token);
return true;
}
catch (Exception exception)
{
map.put("msg","验证失败:"+exception);
}
String json = new ObjectMapper().writeValueAsString(map);
response.setContentType("application/json:charset=UTF=8");
response.getWriter().println(json);
return false;
}
}