springboot整合jwt实现token拦截以及jwt详解

2022-10-11 21:23:22 186 0
魁首哥

jwt实现流程:

1.添加依赖:

 
com.auth0
 java -jwt
3.2.0
  

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();
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 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);
          }
}  
收藏
分享
海报
0 条评论
186
上一篇:PHP匿名函数可以干什么用 下一篇:Unicode 和 UTF-8 是什么关系?

本站已关闭游客评论,请登录或者注册后再评论吧~

忘记密码?

图形验证码