JWT验证

JWT 认证

JSON Web Token

介绍

json web token (jwt) 是一个开放标准(rfc 7519),它定义了一种紧凑的、自包含的方式,用于在各方之间以JSON 对象安全地 传输信息。此信息可以验证和信任,因为他是数字签名的。jwt 可以使用秘钥(使用HMAC算法)或使用 RSA 或 ECDSA 的公钥/私钥对进行签名

通俗解释

JWT 简称 JSON Web Token,也就是通过 JSON 形式作为 Web 应用中的令牌,用于在各方之间安全地将信息作为 JSON 对象传输,在数据传输过程中还可以完成数据加密、签名等相关处理。在这里插入图片描述

JWT 的结构是什么

# 1.令牌的组成
- 1.标头(Header)
- 2.有效载荷(Payload)
- 3.签名(Signatrue)
- 因此,JWT 通常如下所示:xxxxx.yyyyyy.zzzzzzz Header.Payload.Signatrue

- 例子:
Base64(Header).Base64(Payload).HMACSHA256(base64UrlEncode(header)+"."+base64UrlEncode(payload),secret)
# 1.标头(Header)
- 标头通常由两部分组成:令牌的类型(即JWT)和所使用的签名算法,例如 HMACSHA256(写为HS256) 或 RSA。它会使用 Base64 编码组成 JWT 结构的第一部分。

- 注意:Base64 是一种编码,也就是说,它是可以被翻译回原来的样子来的。它并不是一种加密过程。

{
	"alg":"HS256",      默认推荐算法
	"typ":"JWT"
}
# 2.有效载荷(Payload)
- 令牌的第二部分是有效负载,其中包含声明。声明是有关实体 (通常是用户名) 和其他数据的声明。同样的,它会使用 Base64 编码组成 JWT 结构的第二部分
# 2.签名(Signatrue)
- 前面两部分都是使用 Base64 进行编码的,即前端可以解开知道里面的信息。Signature 需要使用编码后的 header 和 payload 以及 我们提供的一个密钥(secret),然后使用 header 中指定的签名算法(HS256)进行签名。签名的作用是保证 JWT 没有被篡改过

- 如 HMACSHA256(base64UrlEncode(header)+"."+base64UrlEncode(payload),secret)

三部分的组成图示

在这里插入图片描述

最后通过 jwt 组合 token 成图示

在这里插入图片描述

使用JWT

依赖 JWT pom 文件

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

生成 token

 Calendar instance = Calendar.getInstance(); //日历类
instance.add(Calendar.SECOND,120000);

//header 有默认的 可以不用设置
String token = JWT.create()
                .withClaim("userId", "21") //payload
                .withClaim("username", "小黑")
                .withExpiresAt(instance.getTime()) //指定令牌的 过期时间
                .sign(Algorithm.HMAC256("dbl"));//签名 括号中的秘钥可以随便写 切记不可泄露

System.out.println(token);

- 输出结果eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE3MDgzNTY3MjIsInVzZXJJZCI6IjIxIiwidXNlcm5hbWUiOiLlsI_pu5EifQ.ZSIzSbhYDd3unuXNTg9nrN57cbjA3iwYPi2o-Z7SZEM

根据 令牌 和 签名解析数据

//创建验证对象
JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256("dbl")).build();
DecodedJWT verify = jwtVerifier.verify(token); //解析token 并可以从当前类中获取存入数据

Claim userId = verify.getClaim("userId");  //获取存入的数据
Claim username = verify.getClaim("username");
System.out.println("过期时间"+verify.getExpiresAt());
System.out.println(userId); //输出
System.out.println(username);

封装工具类

package com.li.utils;
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;
// 简单的封装
public class JWTUtils {

    private static final String TOKEN = "@BanLi";

    //生成 token 三部分
    public static String getToken(Map<String,String> map){
        //创建jwt builder
        JWTCreator.Builder builder = JWT.create();
        //payload
        map.forEach((k,v)->{
            builder.withClaim(k,v);
        });

        Calendar instance = Calendar.getInstance(); //日历类
        instance.add(Calendar.HOUR,2); //有效期是 2个小时

        builder.withExpiresAt(instance.getTime()); //指定过期时间
        return builder.sign(Algorithm.HMAC256(TOKEN));
    }

    // 验证token 合法性 是否有异常    
    public static void verify(String token){
       JWT.require(Algorithm.HMAC256(TOKEN)).build().verify(token);
    }
											//这两个方法 实际就是表达一个意思
    //获取 payload 自包含的数据
    public static DecodedJWT getTokenInfo(String token){
        return  JWT.require(Algorithm.HMAC256(TOKEN)).build().verify(token);
    }
}

在这里插入图片描述

JWT 最好的方式 是作为拦截器

- 拦截器写法
package com.li.config;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.li.utils.JWTUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@Component
@Slf4j
public class JWTInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //1、从 请求头 中获取令牌
        String token = request.getHeader("token");

        //2、校验令牌
        try {
            DecodedJWT tokenInfo = JWTUtils.getTokenInfo(token); // 令牌校验成功
            log.info("令牌中包含的内容:{}",tokenInfo.getClaim("userId").asString());
            return true;
        } catch (Exception e) {
            response.setStatus(404);
            return false;
        }
    }
}
- 注册这个 拦截器 以供全局使用
package com.li.config;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
@Configuration
@Slf4j
public class WebMvcJwt extends WebMvcConfigurer{

    @Autowired
    private JWTInterceptor jwtInterceptor;

    @Override
    protected void addInterceptors(InterceptorRegistry registry) {
        log.info("开启了自定义拦截器");
        registry.addInterceptor(jwtInterceptor)
                .addPathPatterns("/**")  //拦截全部请求
                .excludePathPatterns("/login"); //放行登录
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大板栗~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值