jwt生成token和验证token以及获取playload的数据,实现token拦截

jwt实现流程:

在这里插入图片描述

1.添加依赖:

 <dependency>
    <groupId>com.auth0</groupId>
    <artifactId>java-jwt</artifactId>
    <version>3.2.0</version>
</dependency>

2.编写一个jwt的工具类

package com.springboot.jwt.common;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTCreator;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTDecodeException;
import com.auth0.jwt.interfaces.DecodedJWT;

import java.io.UnsupportedEncodingException;
import java.util.Date;

public class JWTUtil {

    //过期时间设置
    private static final long EXPIRE_TIME = 5 * 60 * 1000;
   // private static final long EXPIRE_TIME = 10 * 1000;
    private static final String SECRET="admintor123service";  //密钥盐
    /**
     * 签名验证
     * @param token
     * @return
     */
    public static boolean verif(String token) {
        try {
            Algorithm algorithm = Algorithm.HMAC256(SECRET);
            JWTVerifier verifier = JWT.require(algorithm).withIssuer("auth0")
                    .build();
            DecodedJWT jwt = verifier.verify(token);
            System.out.println("认证通过:");
            System.out.println("issuer: " + jwt.getIssuer());
            System.out.println("username: " + jwt.getClaim("username").asString());
            System.out.println("过期时间:      " + jwt.getExpiresAt());
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * @param token
     * @return
     */
    public static String getUserName(String token) {
        try {
            DecodedJWT jwt = JWT.decode(token);
            return jwt.getClaim("username").asString();
        } catch (JWTDecodeException e) {
            return null;
        }
    }

    /**
     * 签名生成
     * @param username
     */
        public static String sign(String username) {
        String token = null;
        try {
            Date date = new Date(System.currentTimeMillis() + EXPIRE_TIME);
            Algorithm algorithm = Algorithm.HMAC256(SECRET);
            token = JWT.create().withIssuer("auth0").withClaim("username", username).withExpiresAt(date).sign(algorithm);
            return token;
        } catch (UnsupportedEncodingException e) {
            return null;
        }
    }

}

3.JWT中的三个主要方法和三个对象

在这里插入图片描述
在这里插入图片描述
4.生成token的主要方法:
token = JWT.create().withIssuer(“auth0”).withClaim(“username”, username).withExpiresAt(date).sign(algorithm);
可以看看sign()方法做了什么事情,如下:

在这里插入图片描述

在这里插入图片描述

5.所以生成token需要三部分数据:

5.1.header:头部(一般不需要处理,主要在sign方法传入算法对象即可)

this.headerClaims.put("alg", algorithm.getName());                this.headerClaims.put("typ", "JWT");

5.2.payload:载体(用于配置基本信息和添加其他信息到token)

//基本信息的方法
public JWTCreator.Builder withKeyId(String keyId) {
     this.headerClaims.put("kid", keyId);
     return this;
 }
	//jwt发行者
 public JWTCreator.Builder withIssuer(String issuer) {
     this.addClaim("iss", issuer);
     return this;
 }
//jwt主题
 public JWTCreator.Builder withSubject(String subject) {
     this.addClaim("sub", subject);
     return this;
 }
//接收jwt的用户
 public JWTCreator.Builder withAudience(String... audience) {
     this.addClaim("aud", audience);
     return this;
 }
//jwt的过期时间
 public JWTCreator.Builder withExpiresAt(Date expiresAt) {
     this.addClaim("exp", expiresAt);
     return this;
 }
//在上面时间之前,jwt不可用
 public JWTCreator.Builder withNotBefore(Date notBefore) {
     this.addClaim("nbf", notBefore);
     return this;
 }
//jwt的发行时间
 public JWTCreator.Builder withIssuedAt(Date issuedAt) {
     this.addClaim("iat", issuedAt);
     return this;
 }

 public JWTCreator.Builder withJWTId(String jwtId) {
     this.addClaim("jti", jwtId);
     return this;
 }

//添加其他信息的方法
 public JWTCreator.Builder withClaim(String name, Boolean value) throws IllegalArgumentException {
            this.assertNonNull(name);
            this.addClaim(name, value);
            return this;
        }

5.3.signature:签名(不需要处理,内部方法处理)

签名的生成是由头部数据和载体数据通过算法生成的签名数据。

byte[] signatureBytes = this.algorithm.sign(content.getBytes(StandardCharsets.UTF_8));
String signature = Base64.encodeBase64URLSafeString(signatureBytes);

6.从token中获取payload载体的数据,通过JWT.decode(token)获取DecodeJWT对象。

    public static String getUserName(String token) {
        try {
            DecodedJWT jwt = JWT.decode(token);
            return jwt.getClaim("username").asString();
        } catch (JWTDecodeException e) {
            return null;
        }
    }

说明:
主要通过DecodeJWT对象的getClaim方法获取。chaim对象是一个map,getClaim()就是调用map的get()方法。

7.jwt验证token的载体数据,如果载体的数据与生成token时的载体数据能匹配上,接口的请求就通过,否则不通过,通过拦截器来实现拦截。具体实现如下:

说明:
主要通过JWTVerifier验证器的verify()方法来验证token。

    public static boolean verif(String token) {
        try {
            Algorithm algorithm = Algorithm.HMAC256(SECRET);
            JWTVerifier verifier = JWT.require(algorithm).withIssuer("auth0")
                    .build();
            DecodedJWT jwt = verifier.verify(token);
            return true;
        } catch (Exception e) {
            return false;
        }
    }

看看verify(token)方法做了什么,如下: 说明: 主要验证算法对象,签名,和Claim的数据(也就是payload载体的数据)

在这里插入图片描述

6.1验证算法对象

在这里插入图片描述

6.2验证签名

在这里插入图片描述

6.3Claim的数据(也就是payload载体的数据)

在这里插入图片描述

7.自定义拦截器TokenInterceptor.java,在拦截器中进行token的验证。

package com.springboot.jwt.common.intercepter;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.springboot.jwt.common.JWTUtil;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;

@Component
public class TokenInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
      if(request.getMethod().equals("OPTIONS")){
          response.setStatus(HttpServletResponse.SC_OK);
          return true;
      }

    String token = request.getHeader("token");
    if(token !=null){
        boolean result = JWTUtil.verif(token);
        if(result){
            return true;
        }
    }
        response.setCharacterEncoding("utf-8");
    response.setContentType("application/json;charset=utf-8");
        PrintWriter out = null;
        try{
            Map map = new HashMap<String,Object>();
            map.put("success", false);
            map.put("msg", "认证失败,未通过拦截器");
            response.getWriter().write(new ObjectMapper().writeValueAsString(map));
        }catch (Exception e){
            e.printStackTrace();
            response.sendError(500);
            return false;
        }
        return false;
    }


}

8.在webmvcconfig中,通过重写addInterceptors(InterceptorRegistry registry)方法,注册自定义的过滤器:

package com.springboot.jwt.common.config;

import com.springboot.jwt.common.intercepter.TokenInterceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import java.util.ArrayList;
import java.util.List;
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
/*    private TokenInterceptor tokenInterceptor;
    //构造方法
    public InterceptorConfig(TokenInterceptor tokenInterceptor){
        this.tokenInterceptor =tokenInterceptor;
    }*/
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        List<String> excludePath = new ArrayList<>();
        excludePath.add("/login");//登录
        excludePath.add("/register");//注册
        excludePath.add("/logout");//登出
        excludePath.add("/static/**");  //静态资源
        excludePath.add("/assets/**");  //静态资源
    registry
        .addInterceptor(new TokenInterceptor())
        .addPathPatterns("/**")
        .excludePathPatterns(excludePath);
   // WebMvcConfigurer.super.addInterceptors(registry);
    }
}

  • 5
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值