首页 > 其他分享 >JWT

JWT

时间:2024-02-23 22:36:16浏览次数:35  
标签:令牌 String JWT HS256 Date public

 

1. 介绍

  JWT(JSON Web Token)是一种非常轻量级的规范;使我们能在用户和服务器之间传递安全可靠的消息。

  JWT本质上是一个袖珍的安全令牌,允许我们以一种结构化的方式,在网络上安全的传输数据。

 

2. 构成

  一个JWT实际上就是一个字符串,由三部分组合成:头部、载荷与签名。

  1) 头部(header)是JWT的第一部分,通常是一个JSON对象;包含两个主要部分:令牌的类型(通常是JWT)和所使用的签名算法(比:HMAC SHA256或者RSA)。头部告诉接受方如何验证这个令牌。

{"typ":"JWT","alg":"HS256"} 
下面有{"typ":"JWT","alg":"HS256"}编码后的结果:eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9

  PS:表示JWT的类型是JWT,签名算法是HS256(HMAC SHA-256)。

  编码后的字符串是通过将JSON对象 {"typ":"JWT","alg":"HS256"} 进行Base64 URL编码而得到的。在这个编码后的字符串中,. 被编码为 _+ 被编码为 -/ 被编码为 .,这样可以确保编码后的字符串在URL中安全传输。

  2) 载荷(Payload)是JWT的第二部分,也是一个JSON对象,包含一系列声明。这些声明是关于实体(如用户)及其他数据的声明。载荷是JWT中存储实际数据的部分,可以包含用户ID、角色、权限的数据。

  存储有效信息的地方。包含三部分:

  部分一:标准中注册的声明(建议但不强制,JWT规范默认的属性)

    iss:JWT的签发者(issuer);

    sub:当前令牌的描述说明(subject);

    aud:接收JWT的一方(audience);

    exp:JWT的过期时间,必须大于签发时间(expiration time);

    nbf:定义在什么时间之前,该JWT都是不可用的(not before);

    iat:JWT的签发时间(issued at);

    jti:JWT的唯一身份标识,用于避免重放攻击(JWT ID);

  部分二:公共的声明:可以添加任何信息。通常用于添加用户的相关信息和其他业务需求的必要信息。但不建议添加敏感信息,因为信息可在客户端解密。

  部分三:私有的声明:私有声明是提供者和消费者共同定义的声明,通常用于自定义信息。一般不建议存放敏感信息,因为base64是对称解密,意味着该部分信息可归类为明文信息。

      与标准声明不同的是,私有声明不会被验证,除非明确告知接收方要对这些声明要进行验证和验证规则。

        这个指的就是自定义的claim。比如下面面结构举例中的admin和name都属于自定的claim。
     这些claim跟JWT标准规定的claim区别在于:JWT规定的claim,JWT的接收方在拿到JWT之后,
     都知道怎么对这些标准的claim进行验证(还不知道是否能够验证);而private claims不会验证,除非明确告诉接收方要对这些claim进行验证以及规则才行。 定义一个payload: {"sub":"1234567890","name":"John Doe","admin":true} base64加密结果是:eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9 载荷中只有标准声明是参与校验的,公共和私有是不参与校验的。

  3) 签名(Signature)是JWT的第三部分,由头部、载荷经过Base64编码后的字符串,及一个私钥或盐(secret)共同组成。签名用于验证JWT的真实性和完整性,确保令牌在传输过程中没有被篡改。

  签名 = {base64(header) + base64(payload) + 私钥(盐) } +HS256算法;

  
  https://base64.us/

 

 

3. 代码

  1) 新建一个boot项目

  导入依赖:

        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt</artifactId>
            <version>0.9.0</version>
        </dependency>

        <!-- javax.xml.bind.DatatypeConverter 在Java9 版本后加 ->-->
        <dependency>
            <groupId>javax.xml.bind</groupId>
            <artifactId>jaxb-api</artifactId>
            <version>2.3.1</version>
        </dependency>

 

  2) 加密&解密测试

    // 加密测试
    @Test
    void encryption() {

        JwtBuilder builder= Jwts.builder()      // 用于生成JWT
                .setId("2024")             // 设置唯一编号
                .setSubject("JWT")       // 设置主题  可以是JSON数据
                .setIssuedAt(new Date())  // 设置签发日期
                .setExpiration(new Date(new Date().getTime() + 7 * 24 * 3600 * 1000L))  // 过期时间 当前时间 + 七天的毫秒数
                .signWith(SignatureAlgorithm.HS256,"buildJWT");   // 设置签名 使用HS256算法,并设置SecretKey(字符串)
        // 构建 并返回一个字符串
        System.out.println("结果:" + builder.compact() );
        // eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiIyMDI0Iiwic3ViIjoiSldUIiwiaWF0IjoxNzA4Njk1NTM3LCJleHAiOjE3MDkzMDAzMzd9.CB37ieSRyB0309Ywdv8F7LktR_AzgVGWee7fw23j9t0
     // 头部(token类型、签名加密方式).载荷.签名(包含算法)
    } // 解密测试 @Test public void decrypt(){ String compactJwt = "eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiIyMDI0Iiwic3ViIjoiSldUIiwiaWF0IjoxNzA4Njk1NTM3LCJleHAiOjE3MDkzMDAzMzd9.CB37ieSRyB0309Ywdv8F7LktR_AzgVGWee7fw23j9t0"; Claims claims = Jwts.parser(). setSigningKey("buildJWT"). parseClaimsJws(compactJwt). getBody(); System.out.println(claims); // {jti=2024, sub=JWT, iat=1708695537, exp=1709300337} }

  

  3) 生成工具类

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;

import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;
import java.util.Date;

public class JwtUtil {
    // token 有效期
    public static final Long JWT_TTL = 3600000L;    // 60 * 60 * 1000  一个小时

    // Jwt令牌信息
    public static final String JWT_KEY = "Java_JWT";

    // 创建token方法
    public static String createJWT(String id, String subject, Long ttlMillis) {     // id, 信息, 过期时间
        // 指定算法
        SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;

        // 当前系统时间
        long nowMillis = System.currentTimeMillis();
        //令牌签发时间
        Date now = new Date(nowMillis);
        // 如果令牌有效期为null,则默认设置有效期1小时
        if (ttlMillis == null) {
            ttlMillis = JwtUtil.JWT_TTL;
        }
        // 令牌过期时间设置
        long expMillis = nowMillis + ttlMillis;
        Date expDate = new Date(expMillis);

        // 生成秘钥
        SecretKey secretKey = generalKey();

        // 封装Jwt令牌信息
        JwtBuilder builder = Jwts.builder()
                .setId(id)                    // 唯一的ID
                .setSubject(subject)          // 主题  可以是JSON数据
                .setIssuer("admin")          // 签发者
                .setIssuedAt(now)             // 签发时间
                .signWith(signatureAlgorithm, secretKey) // 签名算法以及密匙
                .setExpiration(expDate);      // 设置过期时间
        // builder.addClaims(map); 可以放一些额外信息;
        return builder.compact();
    }

    /**
     * 生成加密 secretKey
     * @return
     */
    public static SecretKey generalKey() {
        byte[] encodedKey = Base64.getEncoder().encode(JwtUtil.JWT_KEY.getBytes()); // 转为字节码
        SecretKey key = new SecretKeySpec(encodedKey, 0, encodedKey.length, "AES");
        return key;
    }


    /**
     * 解析令牌数据
     * @param jwt
     * @return
     * @throws Exception
     */
    public static Claims parseJWT(String jwt) throws Exception {
        SecretKey secretKey = generalKey();
        return Jwts.parser()
                .setSigningKey(secretKey)
                .parseClaimsJws(jwt)
                .getBody();
    }

}

  4) 测试

    public static void main(String[] args) {

        // 加密
        String encryptionToken = JwtUtil.createJWT("007", "学Java的bei", 7 * 24 * 3600 * 1000L);
        System.out.println("加密:" + encryptionToken);

        // 加密:eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiIwMDciLCJzdWIiOiLlraZKYXZh55qEYmVpIiwiaXNzIjoiYWRtaW4iLCJpYXQiOjE3MDg2OTc5MDEsImV4cCI6MTcwOTMwMjcwMX0.W0D-u0KcIG1Uiz8WN12s0xYR1f3abdzeM5iFrHd8umc

        System.out.println("·····································································");
        
        // 解密
        String decryptToken = "eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiIwMDciLCJzdWIiOiLlraZKYXZh55qEYmVpIiwiaXNzIjoiYWRtaW4iLCJpYXQiOjE3MDg2OTc0MjUsImV4cCI6MTcwOTMwMjIyNX0.HxE5aoGLAPxXJIjdcEynJ6d1v_KAwnC0I4G7R89YDKw";
        try {
            System.out.println("解密:" + parseJWT(decryptToken));
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        // 解密:{jti=007, sub=学Java的bei, iss=admin, iat=1708697425, exp=1709302225}
        
    }

 

  4. 注册

 

  5. JWT的工作原理

 

  6. JWT的登陆验证

 

标签:令牌,String,JWT,HS256,Date,public
From: https://www.cnblogs.com/warmNest-llb/p/18030484

相关文章

  • JWT认证和授权
    1.JWT的组成部分A.头部(Header):它包含了token的类型,即JWT,以及用于生成签名的算法信息,例如HMACSHA256或RSA。在JWT中,头部通常是一个JSON对象,例如{"alg":"HS256","typ":"JWT"}。B.载荷(Payload):这部分包含了声明(Claim),也就是一些关于实体的陈述,如主题、发行者、过期时间等。这......
  • SpringSecurity与JWT如何实现项目端分离认证与授权
    ✅SpringSecurity+JWT实现项目前端分离认证授权✅1.简介SpringSecurity是Spring家族中的一个安全管理框架。相比与另外一个安全框架Shiro,它提供了更丰富的功能,杜区资源也比Shiro丰富。一般来说中大型的项目都是使用SpringSecurity来做安全框架。小项目有Shiro的比较多,因......
  • c-jwt-cracker Jwt 密钥爆破工具的安装使用
    c-jwt-cracker  项目地址:https://github.com/brendan-rius/c-jwt-cracker BuildaDockerImagedockerbuild.-tjwtcrack RunonDocker  docker版使用方法dockerrun-it--rmjwtcrackeyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODk......
  • djangorestframework-simplejwt 的使用
    djangorestframework-simplejwt使用转载于:https://www.cnblogs.com/liuqingzheng/p/179422271快速使用1.1配置#1安装pipinstalldjangorestframework-simplejwt#2路由层fromrest_framework_simplejwt.viewsimporttoken_obtain_pair,token_verify,token_refre......
  • JwtAuthenticationTokenFilter
    packagecom.oep.backend.config.filter;//实现config.filter.JwtAuthenticationTokenFilter类,用来验证jwttoken,如果验证成功,则将User信息注入上下文中importcom.oep.backend.mapper.AccountMapper;importcom.oep.backend.pojo.Account;importcom.oep.backend.service......
  • src.backend.utils.JwtUtil
    packagecom.oep.backend.utils;importio.jsonwebtoken.Claims;importio.jsonwebtoken.JwtBuilder;importio.jsonwebtoken.Jwts;importio.jsonwebtoken.security.SecureDigestAlgorithm;importorg.springframework.stereotype.Component;importjavax.crypto.Sec......
  • [陇剑杯 2021]jwt
    前置首先了解一下什么是jwt普通的token认证过程如下,和jwt的区别主要存在于第3和第7步  jwt的组成由以下的部分组成,各部分用点隔开 解题打开数据包发现只有http和tcp两种流 追踪tcp流查看具体的每个包(数据包右键) 在第1个流那里发现了请求头中携带了特殊的token,正......
  • SpringBoot简单集成JWT
    1.JWT入门1.1JWT概念官方网站:https://jwt.io/introduction/JSONWebToken(JWT)是一个定义在RFC7519开放标准下的技术,提供了一种紧凑且自包含的方式用于在各方之间安全地传输信息。JWT使用JSON对象作为载体,同时通过数字签名来验证和确保信息的可信度。数字签名可以通过......
  • JWT Token 刷新方案
    一:什么是JWTJWT(JSONWebToken)是目前最流行的跨域认证解决方案,是一种基于Token的认证授权机制。从JWT的全称可以看出,JWT本身也是Token,JWT自身包含了身份验证所需要的所有信息。因此,服务端不需要存储session信息,大大减轻了服务端的压力。JWT本质上就是一组字符串,通过"."切割......
  • JWT的生成和校验
    JWT(JSONWebToken)是一种开放标准(RFC7519),用于在网络上安全传输信息的简洁、自包含的方式。它通常被用于身份验证和授权机制。JWT由三部分组成:头部(Header)、载荷(Payload)和签名(Signature)。1、头部(Header):包含了关于生成该JWT的信息以及所使用的算法类型。2、载荷(payload): ......