• 欢迎光临~

SpringBoot集成JWT

开发技术 开发技术 2022-07-24 次浏览

一、JWT的简述

JWT 是Json Web Token的简称;JWT由头部(header)、载荷(payload)、签证(signature)三部分组成;其三部分之间用.分隔,例如:

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6IjEiLCJleHAiOjE2NTkxMDU0MTIsInVzZXJuYW1lIjoiemhhbmdzYW4ifQ.ciurjE4dS3CBckl25Df6eaQvzJIuiM5Wk-LD_gfoEBs

1. 头部-header

jwt的头部承载两部分信息

  • 声明类型,这里时jwt
  • 声明加密的算法,通常直接使用 HMAC SHA256

如:

{
  'typ': 'JWT',
  'alg': 'HS256'
}
使用base64加密,构成第一部分:eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9

2.载荷-payload

载荷就是存放有效信息的地方,包含三个部分

  标准中注册的声明
  公共的声明
  私有的声明
这其中标准中注册的声明(建议但不强制使用)包括如下部分

  iss : jwt签发者
  sub: jwt面向的用户
  aud: 接收方
  exp: jwt过期时间
  nbf: 定义在什么时间之前,jwt都是不可用的
  iat: jwt签发时间
  jwt唯一身份标识
公共声明存放用户或业务等相关信息

私有声明是提供者和消费者所共同定义的声明,一般不建议存放敏感信息,因为base64是对称解密的,意味着该部分信息可以归类为明文信息

如:

{
  "sub": "18700000000",
  "name": "songweipeng",
  "admin": true
}

BASE64 加密

eyJpZCI6IjEiLCJleHAiOjE2NTkxMDU0MTIsInVzZXJuYW1lIjoiemhhbmdzYW4ifQ

var encodedString = base64UrlEncode(header) + '.' + base64UrlEncode(payload);

var signature = HMACSHA256(encodedString, '密钥');

加密之后,得到signature签名信息。

ciurjE4dS3CBckl25Df6eaQvzJIuiM5Wk-LD_gfoEBs

3.签证-signature

jwt的第三部分是一个签证信息,这个签证信息由三部分组成

二、SpringBoot 集成

2.1 jwt依赖

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

2.2 获取token的工具类 

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTCreator;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.DecodedJWT;
import java.util.Calendar;
import java.util.Map;

/**
 * @Project:
 * @Description:
 * @Auther: songwp
 * @Date: 2022/7/22 22:23
 **/
public class JWTUtils {

    private static final String SING = "@#%$^&lu123456";

    /**
     * 生成token
     */
    public static String getToken(Map<String,String> map){
        Calendar instance = Calendar.getInstance();
        //默认7天过期
        instance.add(Calendar.DATE,7);
        //创建jwt builder
        JWTCreator.Builder builder = JWT.create();

        map.forEach((k,v)->{
            builder.withClaim(k,v);
        });

        String token = builder.withExpiresAt(instance.getTime())
                .sign(Algorithm.HMAC256(SING));
        return token;
    }

    /**
     * 验证token合法性
     */
    public static DecodedJWT verify(String token){
        return JWT.require(Algorithm.HMAC256(SING)).build().verify(token);
    }

2.3 创建拦截器

import com.auth0.jwt.exceptions.AlgorithmMismatchException;
import com.auth0.jwt.exceptions.SignatureVerificationException;
import com.auth0.jwt.exceptions.TokenExpiredException;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.songwp.hutooldemo.untils.JWTUtils;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.Map;

/**
 * @Project:
 * @Description:
 * @Auther: songwp
 * @Date: 2022/7/22 22:31
 **/
public class JWTInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        Map<String, Object> map = new HashMap<>();

        //获取请求头中的令牌
        String token = request.getHeader("token");

        try {
            //验证令牌
            DecodedJWT verify = JWTUtils.verify(token);
//            String id = verify.getClaim("id").asString();
//            String username = verify.getClaim("username").asString();
//            System.out.println("============="+id);
//            System.out.println("============="+username);
            return true;
        } catch (SignatureVerificationException e){
            e.printStackTrace();
            map.put("msg","无效签名");
        } catch (TokenExpiredException e){
            e.printStackTrace();
            map.put("msg","token过期");
        } catch (AlgorithmMismatchException e){
            e.printStackTrace();
            map.put("msg","token算法不一致");
        } catch (Exception e){
            e.printStackTrace();
            map.put("msg","token无效");
        }
        map.put("state","flase");

        //将map转为json
        String json = new ObjectMapper().writeValueAsString(map);
        response.setContentType("application/json;charset=UTF-8");
        response.getWriter().println(json);
        return false;

    }
}

2.4 拦截器注册

/**
* @Project:
* @Description:
* @Auther: songwp
* @Date: 2022/7/22 22:33
**/

import com.songwp.hutooldemo.interceptor.JWTInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

/**
* 注册拦截器
*/
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {

/**
* 配置跨域访问
* @param registry
*/
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")//项目中的所有接口都支持跨域
.allowedOrigins("*")//所有地址都可以访问,也可以配置具体地址
.allowCredentials(true)
.allowedMethods("*")//"GET", "HEAD", "POST", "PUT", "DELETE", "OPTIONS"
.maxAge(3600);// 跨域允许时间
}

/**
* 注册拦截器
* @param registry
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new JWTInterceptor())
//拦截
.addPathPatterns("/user/test")
//放行
.excludePathPatterns("/user/login");
}

@Bean
public JWTInterceptor tokenInterceptor(){
return new JWTInterceptor();
}
}
程序员灯塔
转载请注明原文链接:SpringBoot集成JWT
喜欢 (0)