token令牌分为三部分:Header(头部):放着签名算法和令牌类型(token就是一种令牌类型),payload(负载):可以放着一些自定义字段,存储的时候会被Base64编码,Signature(签名):对Header和Payload进行编码的结果,通过指定的签名算法和密钥来进行计算。这三部分由.分割。
步骤1:引入jwt相关依赖
<!--jwt依赖-->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
<version>${jwt}</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
<version>${jwt}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId>
<version>${jwt}</version>
<scope>runtime</scope>
</dependency>
步骤2:创建Jwt工具类
jwt工具类用于生成jwt的token令牌,解析token令牌,还有判断令牌是否有效。
定义密钥和过期时间
private static final String SECRET="SECRET="eyJ1c2VybmFtZSI6ImRqIiwicGFzc3dvcmQiOjEyMzQ1Nn0=";//定义密钥";
private static final Long EXPIRATION = 3600L; //定义过期时间
密钥可以去浏览器的base64编码生成器来获得。通过自己指定的数据来进行编码。
生成token令牌的方法
//生成令牌
public static String generateToken(Map<String, String> claims) {
return Jwts.builder()
.setClaims(claims)//传入自定义数据
.setExpiration(new Date(System.currentTimeMillis() + EXPIRATION * 1000))//生成过期时间
.signWith(SignatureAlgorithm.HS256, SECRET)//签名算法和密钥
.compact();
}
setClaims用来组成token令牌的Payload,比如接收到前端传过来的用户名和id,可以封装成一个Map集合作为参数传进去,setExpiration用来指定过期时间,多久会失效,这里是当前时间加上刚刚定义的时间,signWith传递的是签名算法和密钥。
解析token令牌的方法
public static Claims parseToken(String token) {
return Jwts.parser()
.setSigningKey(SECRET)
.parseClaimsJws(token)
.getBody();
}
setSigningKey传入生成token令牌的密钥,parseClaimsJws传入获得到的token令牌。这个方法主要用于校验token是否有效,比如结合下面的方法。
校验token令牌
public static boolean validateToken(String token) {
try {
parseToken(token);
return true;
} catch (Exception e) {
return false;
}
如果报错了,说明令牌有问题,比如过期之类的,执行一些逻辑,比如跳转到登录界面,如果没报错,就证明令牌有效。
步骤3:创建一个拦截器
创建一个类实现HandlerInterceptor接口,实现里面的perHandle方法。
@Slf4j
@Component
public class JwtTokenInterceptor implements HandlerInterceptor {
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
if (!(handler instanceof HandlerMethod)) {
//当前拦截到的不是动态方法,直接放行
return true;
}
// 1. 从请求头获取Token
String token = request.getHeader("token");
if (token == null || !token.startsWith("Bearer ")) {
log.info("token为空:{}",token);
response.setStatus(401);
return false;
}
token = token.substring(7);
boolean flag = JwtUtil.validateToken(token);
if (flag) {
return true;
}
log.info("token无效:{}",token);
response.setStatus(401);
return false;
}
主要就是拦截后的逻辑,先从请求头拿到浏览器被前端拿到的token,如果无效就返回401状态码,并且返回一个false。boolean类型的返回值用于告诉拦截器,什么时候放行,什么时候不放。
步骤四:注册拦截器
创建了一个拦截器后,肯定是要去配置,启动的,这里创建了一个配置类,并且实现了WebMvcConfigurer接口 重写了addInterceptors这个方法。
@Configuration
@Slf4j
public class WebMvcConfiguration implements WebMvcConfigurer {
@Autowired
private JwtTokenInterceptor jwtTokenInterceptor;
/*@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(jwtTokenInterceptor)
.addPathPatterns("/*") // 拦截路径
.excludePathPatterns("/admin/login"); // 排除路径
}*/
将刚刚编写的拦截器依赖注入,然后在方法里面开始注册,这里注册的时候指定了拦截的路径,排除拦截的路径,比如登陆时的路径。
以上是我对token令牌登录校验功能的一个理解,希望这篇博客可以对你有帮助。有不足的地方页欢迎一起到评论区进行交流讨论