spring boot集成JWT实现token验证

Posted 江州益彤

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了spring boot集成JWT实现token验证相关的知识,希望对你有一定的参考价值。

JWT的主要应用场景

身份认证在这种场景下,一旦用户完成了登陆,在接下来的每个请求中包含JWT,可以用来验证用户身份以及对路由,服务和资源的访问权限进行验证。由于它的开销非常小,可以轻松的在不同域名的系统中传递,所有目前在单点登录(SSO)中比较广泛的使用了该技术。 信息交换在通信的双方之间使用JWT对数据进行编码是一种非常安全的方式,由于它的信息是经过签名的,可以确保发送者发送的信息是没有经过伪造的。

优点

1.简洁(Compact): 可以通过URL,POST参数或者在HTTP header发送,因为数据量小,传输速度也很快
2.自包含(Self-contained):负载中包含了所有用户所需要的信息,避免了多次查询数据库
3.因为Token是以JSON加密的形式保存在客户端的,所以JWT是跨语言的,原则上任何web形式都支持。
4.不需要在服务端保存会话信息,特别适用于分布式微服务。

JWT的结构

JWT由三段信息用.连接构成的字符串。
Header.Payload.Signature
例如:
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJhdWQiOiIxIiwiZXhwIjoxNjQ4MTgzMTkxfQ.vAFH5Ok5BtCYKutyg_jqtT7eJYOXw3xBPMBpveIxuf4

使用

导入依赖

<!-- https://mvnrepository.com/artifact/com.auth0/java-jwt -->
<dependency>
    <groupId>com.auth0</groupId>
    <artifactId>java-jwt</artifactId>
    <version>3.10.3</version>
</dependency>

生成Token

package com.ermao.utils;

import cn.hutool.core.date.DateUtil;
import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;

import java.util.Date;

public class TokenUtils 
    public static String getToken(String userId, String sign) 
        return JWT.create().withAudience(userId) // 将 user id 保存到 token 里面
                .withExpiresAt(DateUtil.offsetHour(new Date(), 2)) //2小时后token过期
                .sign(Algorithm.HMAC256(sign)); // 以 password 作为 token 的密钥
    

创建拦截器拦截token

package com.ermao.common.interceptor;

import cn.hutool.core.util.StrUtil;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTDecodeException;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.ermao.common.Constants;
import com.ermao.entity.User;
import com.ermao.exception.ServiceException;
import com.ermao.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import com.auth0.jwt.JWT;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class JwtInterceptor implements HandlerInterceptor 
    @Autowired
    UserService userService;

    public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object object) throws Exception 
        String token = httpServletRequest.getHeader("token");// 从 http 请求头中取出 token
        // 如果不是映射到方法直接通过
        if (!(object instanceof HandlerMethod)) 
            return true;
        
        //执行验证
        if(StrUtil.isBlank((token)))
            throw new ServiceException(Constants.CODE_401,"无token,请重新登录");
        
        //获取token中的userID
        // 获取 token 中的 user id
        String userId;
        try 
            userId = JWT.decode(token).getAudience().get(0);
         catch (JWTDecodeException j) 
            throw new ServiceException(Constants.CODE_401,"无token,请重新登录");
        
        User user = userService.getById(userId);
        if (user == null) 
            throw new ServiceException(Constants.CODE_401,"用户不存在,请重新登录");
        
        // 验证 token
        JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(user.getPassword())).build();
        try 
            jwtVerifier.verify(token);
         catch (JWTVerificationException e) 
            throw new ServiceException(Constants.CODE_401,"无token,请重新登录");
        
      return true;
    


注册拦截器

package com.ermao.config;

import com.ermao.common.interceptor.JwtInterceptor;
import org.springframework.context.annotation.Bean;
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 InterceptorConfig implements WebMvcConfigurer 
    public void addInterceptors(InterceptorRegistry registry) 
        registry.addInterceptor(jwtInterceptor())
                .addPathPatterns("/**")    // 拦截所有请求,通过判断是否有 @LoginRequired 注解 决定是否需要登录
                .excludePathPatterns("/user/login","/user/register","/**/exportExcel","/**/importExcel");

    
    @Bean
    public JwtInterceptor jwtInterceptor() 
        return new JwtInterceptor();
    


使用

以上是关于spring boot集成JWT实现token验证的主要内容,如果未能解决你的问题,请参考以下文章

redis jwt spring boot spring security 实现api token 验证

Spring boot + JWT 实现安全验证 ---auth0.jwt

Spring Boot + Security + JWT 实现Token验证+多Provider——登录系统

spring boot2整合shiro安全框架实现前后端分离的JWT token登录验证

Spring Boot如何集成Security实现安全认证

spring boot 2 集成JWT实现api接口认证