Jwt验证

JWT验证

Jwt结构

json web token 其实就是一个字符串 string令牌

header.payload.singnature

1、标头(Header)

令牌类型(即jwt) + 使用的签名算法

{
    “alg”:"HS256",     //签名算法,还有HMAC,RSA,SHA256
    "typ":"jwt"		   //令牌类型,JWT
}

最后通过Base64编码加密组成字符串变成JWT的一部分。

2、有效载荷(Payload)

​ 令牌的第二部分,有效负载,包含有关实体和其他数据的声明,除敏感信息,同样使用Base64组码加密组成JWT第二部 分

{
	“sub”:"123456",
    "name":"John Doe",
    "admin":true
}

3、签名(Signature)

​ Signature需要使用编码后的header和payload以及我们提供的密钥,再使用header指定的算法(HS256)进行签名。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1Tzc28gr-1657443961221)(C:\Users\17864\AppData\Roaming\Typora\typora-user-images\image-20220710132537685.png)]

​ **签名的作用保证被篡改的数据不会通过 **

4、总的jwt结构就是

header.payload.Signature(header+payload+私钥)

签名的目的:最后一步签名的过程中,实际是对头部以及负载内容进行的签名,防止内容被串改,如果有人对头部以及负载的内容解码之后进行修改,再进行修改加上签名组成新的jwt后,服务端会判断除新的头部和负载形成签名和JWT附带的签名不一样的。如果对新的头部和负载进行签名时候,在不知道服务器加密时用的公钥的话,得出来的签名也是不一样的。

在这里插入图片描述

最后Base64编码后

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DM0pt8ID-1657443961223)(C:\Users\17864\AppData\Roaming\Typora\typora-user-images\image-20220710140140981.png)]

header:红色 payload:紫色 signature:蓝色

JWT使用

第一步:引入依赖

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

第二步:生成token

    //生成token
    @Test
    public void getToken(){
        long EXPIRE_TIME =30*60*1000;                   //30分钟过期时间

        //获取时间,作为token的过期时间,设置为30分钟
        Date deadline = new Date(System.currentTimeMillis() + EXPIRE_TIME);

        HashMap<String, Object> map = new HashMap<>();
        String sign = JWT.create().withHeader(map)      //header,暂不设置。
                .withClaim("userId", 12)    //payload 存储非敏感的信息 例如用户账号,不能存密码,防止被人解析
                .withClaim("username","bindada")
                .withExpiresAt(deadline)                //指定令牌的过期时间
                .sign(Algorithm.HMAC256("!we2123"));    //签名  保密复杂
        System.out.println(sign);                       //输出token
    }

第三步:verify验证token

    @Test
    public void verify(){
        //创建验证对象  注意:验证时候一定要和生成时的 算法 和 签名 一致。
        JWTVerifier build = JWT.require(Algorithm.HMAC256("!we2123")).build();
        DecodedJWT verify = build.verify("eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE2NTc0MzkxNTcsInVzZXJJZCI6MTIsInVzZXJuYW1lIjoiYmluZGFkYSJ9.Eb4VKwitXlXq0qvZW3fOWXTY-69ZfzrzqAbacSaMdUA");
        //以上两行已经完成验证了,若没异常就验证成功!有误就验证失败,前提保证算法一定的一致。

        //获取payload存储信息
        System.out.println(verify.getClaims().get("userId").asInt()); //存什么类型,就用什么as方法,否则会null。
        System.out.println(verify.getClaims().get("username").asString());

        //查看token过期时间
        Date expiresAt = verify.getExpiresAt();
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String format = simpleDateFormat.format(expiresAt);
        System.out.println(format);
    }

异常类型

# 签名验证异常 (生成时和验证时的签名不一致,会出现此异常)
 - SignatureVerificationException
# 算法不匹配异常  (生成时和验证时的算法不一致,会出现此异常)
 - AlgorithmMismatchException
# 令牌过期异常 (生成时设置的时间超时后,再次验证会出现此异常)
 - TokenExpiredException
# 失效的payload异常  (出现此异常的原因有:可能有人使用base64解析payload,更改了数据payload里解析的数据,再次传过来,验证时会出现此异常)
 - InvalidClaimException

JwtUtil工具类

package com.bindada.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.Date;
import java.util.Map;

/*
*   @Description  JwtUtil的工具类
*   @Author  bindada  2022/7/10 21:12
*/
public class Jwtutil {

    private static final String SING = "!AFGYO8*$@%";   //服务器签名

    private static final long EXPIRE_TIME = 120*60*1000; //毫秒级,2个小时

    /*
    *   生成token   格式:header.payload.sing
    */
    public static String getToken(Map<String,String> map){
        Date date = new Date(System.currentTimeMillis() + EXPIRE_TIME);        //过期时间
        JWTCreator.Builder builder = JWT.create();
        //payload
        map.forEach((k,v)->{
            builder.withClaim(k,v);    //遍历存储payload信息
        });
        String token = builder.withExpiresAt(date).sign(Algorithm.HMAC256(SING));  //设置令牌时间和签名加密
        return token;
    }

    /*
    *   验证token合法性
    */
    public static DecodedJWT verify(String token){
        //注意:验证时候一定要和生成时的 算法 和 签名SING 一致。
            return JWT.require(Algorithm.HMAC256(SING)).build().verify(token);
    }

    /*
    *   获得token中的信息
    */
    public static DecodedJWT getTokenInfo(String token){
        DecodedJWT decode = JWT.decode(token);
        //decode.getClaims().get("username");
        return decode;
    }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值