SpringBoot集成JWT

一、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);
    }

   /**
    * 根据token获取载荷信息
    * @param token
    * @return
    */
   public static Map<String, Claim> getPayloadByToken(String token) {
      return verify(token).getClaims();
   }

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 {
    String token = request.getHeader("Authorization");
    Result<T> result = new Result<T>();
  try {
  //验证令牌
  DecodedJWT verify = JwtUtils.verify(token);
  UserTokenInfoHolder.setUserTokenInfo(verify.getClaims());
  return true;
  } catch (SignatureVerificationException e) {
   e.printStackTrace();
   result.setCode(-1);
   result.setMessage("无效签名");
  } catch (TokenExpiredException e) {
  e.printStackTrace();
  result.setCode(-1);
  result.setMessage("token过期");
  } catch (AlgorithmMismatchException e) {
  e.printStackTrace();
  result.setCode(-1);
   result.setMessage("token算法不一致");
  } catch (JWTDecodeException e) {
  e.printStackTrace();
   result.setCode(-1);
   result.setMessage("token不合法");
  } catch (NullPointerException e) {
   e.printStackTrace();
   result.setCode(-1);
  result.setMessage("token不能为空");
  } catch (Exception e) {
  e.printStackTrace();
   result.setCode(-1);
  result.setMessage("token无效");
  }
    //将返回值result转为json
    String json = new ObjectMapper().writeValueAsString(result);
    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();
}
}
posted @ 2022-07-24 18:37  奋--斗  阅读(393)  评论(0编辑  收藏  举报