JWT的入门学习和JWTUtils封装

JWT长的什么样

JWT是由三段信息构成的,将这三段信息文本用点.链接一起就构成了Jwt字符串。就像这样:
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE1OTg0MjU5MzIsInVzZXJJZCI6MTExLCJ1c2VybmFtZSI6Ik1hcmtaUVAifQ.PTlOdRG7ROVJqPrA0q2ac7rKFzNNFR3lTMyP_8fIw9Q

JWT的构成

第一部分我们称它为头部(header),第二部分我们称其为载荷(payload, 类似于飞机上承载的物品),第三部分是签证(signature).

header

jwt的头部承载两部分信息:

  • 声明类型,这里是jwt
  • 声明加密的算法 通常直接使用 HMAC SHA256

payload

载荷就是存放有效信息的地方。有效载荷包含三个部分

  • 标准注册声明
    iss:jwt的签发者/发行人;
    sub:主题;
    aud:接收方;
    exp:jwt过期时间;
    nbf:jwt生效时间;
    iat:签发时间
    jti:jwt唯一身份标识,可以避免重放攻击
  • 公共声明:
    可以在公共声明添加任何信息,我们一般会在里面添加用户信息和业务信息,但是不建议添加敏感信息,因为公共声明部分可以在客户端解密。
  • 私有声明:
    私有声明是服务器和客户端共同定义的声明,同样这里不建议添加敏感信息。
    如;我们一般在有效载荷里面放置;
{
		"userId": 88782,
		"username": "Mark",
		"role": "admin"
}

signature

jwt的第三个部分是一个签证信息,这个签证信息由三部分组成

  • header (base64后的)
  • payload (base64后的)
  • secret

注意:secret是保存在服务器端的,jwt的签发生成也是在服务器端的,secret就是用来进行jwt的签发和jwt的验证,所以,它就是你服务端的私钥,在任何场景都不应该流露出去。一旦客户端得知这个secret, 那就意味着客户端是可以自我签发jwt了。

用代码来生成一串token

新建一个Springboot项目

导入依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.2.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.jwttest</groupId>
    <artifactId>jwt</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>jwt</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <!--引入JWT得依赖-->
        <dependency>
            <groupId>com.auth0</groupId>
            <artifactId>java-jwt</artifactId>
            <version>3.4.0</version>
        </dependency>

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

直接在测试类上写token的生成与解析

package com.jwttest;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.DecodedJWT;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;

import java.util.Calendar;
import java.util.HashMap;
import java.util.Map;

@SpringBootTest
class JwtApplicationTests {

    @Test
    void tokenProduces() {
        Map<String, Object> map = new HashMap<>();
        Calendar instance = Calendar.getInstance();
        instance.add(Calendar.DATE,7);
        String token = JWT.create().withHeader(map)    //生成token的header这一部分为令牌类型和所使用得签名算法,这个是默认的,可以不写
                .withClaim("userId", 111) //生成token的payload部分,通常是放一些用户信息进去,如id,名字,权限等,千万不要放密码
                .withClaim("username", "MarkZQP")
                .withExpiresAt(instance.getTime())   //设token的过期时间
                .sign(Algorithm.HMAC256("ksjfkjsakfjkajk"));  //签名的算法及密钥,这里面的一串字符串是不能泄露的

        System.out.println(token); //将token打印出来可以看出它是三段式的

    }

    @Test
    void tokenVerify(){

        //在验证过程中会报各种异常:1. 算法不一致 ---这个是最开始验证的
        //                         2. 签名不一致
        //                         3. token过期
        //                         4. 失效的payload

        //创建验证对象
        JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256("ksjfkjsakfjkajk")).build();
        DecodedJWT verify = jwtVerifier.verify("eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE1OTg0MjU5MzIsInVzZXJJZCI6MTExLCJ1c2VybmFtZSI6Ik1hcmtaUVAifQ.PTlOdRG7ROVJqPrA0q2ac7rKFzNNFR3lTMyP_8fIw9Q");

        //解出token里面传入的对象信息
        System.out.println(verify.getClaim("userId").asInt());//因为传入的是int所以需要改成asInt()
        System.out.println(verify.getClaim("username").asString());
        System.out.println("过期时间"+verify.getExpiresAt()); //打印过期时间

    }

}

** 代码中写了两个方法,一个是Token的生成,一个是Token的解析验证,在实际验证中,我们当然不是这样写,我们一般写成Utils工具类,这样更加方便使用**

JWTUtils工具类封装

封装工具类,将上面的代码,类似的封装进去,与上面不同的时,payload部分,我们将用户信息等通过参数来传递

package com.jwttest.utils;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTCreator;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.DecodedJWT;
import jdk.internal.dynalink.beans.StaticClass;

import java.util.Calendar;
import java.util.Map;
import java.util.Stack;

public class JWTUtils {
    private static final String SING = "ldjfklajsfjas";

    /**
     * 生成Token  header.payload.sign
     */
    public static String getToken(Map<String, String> map) {
        Calendar instance = Calendar.getInstance();
        instance.add(Calendar.DATE, 7); //默认7天过期
        //创建jwt builder
        JWTCreator.Builder builder = JWT.create();

        //payload
        map.forEach((k,v)->{
            builder.withClaim(k,v);
        });


        String token = builder.withExpiresAt(instance.getTime())
                                .sign(Algorithm.HMAC256(SING));
        return token;
    }

    /**
     *  验证token的合法性
     */
    public static void verify(String token){
        JWT.require(Algorithm.HMAC256(SING)).build().verify(token);  //这一行代码就可以起到验证的作用,因为在验证不匹配时它自动会抛出异常
    }

    /**
     * 获取token的信息方法
     */
    public static DecodedJWT getTokenInfo(String token){
        DecodedJWT verify = JWT.require(Algorithm.HMAC256(SING)).build().verify(token);
        return verify;
    }
}

在封装完JWT工具类后,在后面就直接可以与Springboot进行集成了。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值