欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

如何使用JJWT及JWT讲解和工具类

程序员文章站 2022-04-06 22:07:54
目录1. 什么是jwt2. jwt的构成2.1 头部(header)3. jjwt的介绍4. jjwt的使用5. jwt工具类1. 什么是jwtjson web token(jwt)是一个轻量级的认证...

1. 什么是jwt

json web token(jwt)是一个轻量级的认证规范,这个规范允许我们使用jwt在用户和服务器之间传递安全可靠的信息。其本质是一个token,是一种紧凑的url安全方法,用于在网络通信的双方之间传递。

2. jwt的构成

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

2.1 头部(header)

头部用于描述关于该jwt的最基本的信息,例如其类型以及签名所用的算法等

头部可以被表示成一个json对象

{"typ":"jwt","alg":"hs256"}

在头部指明了签名算法是hs256算法。 我们进行base64编码,编码后的字符串如下:

eyj0exaioijkv1qilcjhbgcioijiuzi1nij9

base64是一种基于64个可打印字符来表示二进制数据的表示方法。

由于2的6次方等于64,所以每6个比特为一个单元,对应某个可打印字符。

三个字节有24个比特,对应于4个base64单元,即3个字节需要用4个可打印字符来表示。

jdk 中提供了非常方便的 base64encoder 和 base64decoder,用它们可以非常方便的完成基于 base64 的编码和解码

2.2 载荷(playload)

载荷是存放有效信息的地方,这些有效信息包含三个部分:

2.2.1 标准中注册的声明(建议但不强制使用)

iss: jwt签发者
sub: jwt所面向的用户
aud: 接收jwt的一方
exp: jwt的过期时间,这个过期时间必须要大于签发时间
nbf: 定义在什么时间之前,该jwt都是不可用的.
iat: jwt的签发时间
jti: jwt的唯一身份标识,主要用来作为一次性token,从而回避重放攻击。

2.2.2 公共的声明

公共的声明可以添加任何的信息,一般添加用户的相关信息或其他业务需要的必要信息。但不建议添加敏感信息,因为该部分在客户端可解密

2.2.3 私有的声明

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

比如下面举例中的admin和name都属于自定的claim。这些claim跟jwt标准规定的claim区别在于:jwt规定的claim,jwt的接收方在拿到jwt之后,都知道怎么对这些标准的claim进行验证;而private claims不会验证,除非明确告诉接收方要对这些claim进行验证以及验证的规则

定义一个payload:

{"sub":"1234567890","name":"john doe","admin":true}

然后将其进行base64加密,得到jwt的第二部分:

eyjzdwiioiixmjm0nty3odkwiiwibmftzsi6ikpvag4grg9liiwiywrtaw4ionrydwv9

2.3 签证(signature)

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

header (base64后的)

payload (base64后的)

secret

这个部分需要base64加密后的header和base64加密后的payload使用.连接组成的字符串,然后通过header中声明的加密方式进行加盐secret组合加密,然后就构成了jwt的第三部分:

tjva95orm7e2cbab30rmhrhdcefxjoyzgefonfh7hgq

将这三部分用.连接成一个完整的字符串,构成了最终的jwt:

eyjhbgcioijiuzi1niisinr5cci6ikpxvcj9.eyjzdwiioiixmjm0nty3odkwiiwibmftzsi6ikpvag4grg9liiwiywrtaw4ionrydwv9.tjva95orm7e2cbab30rmhrhdcefxjoyzgefonfh7hgq

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

3. jjwt的介绍

jjwt是一个提供端到端的jwt创建和验证的java库

官方文档:

4. jjwt的使用

<!--鉴权-->
<dependency>
    <groupid>io.jsonwebtoken</groupid>
    <artifactid>jjwt</artifactid>
    <version>0.9.0</version>
</dependency>
import com.sun.scenario.effect.impl.sw.sse.sseblend_src_outpeer;
import io.jsonwebtoken.claims;
import io.jsonwebtoken.jwtbuilder;
import io.jsonwebtoken.jwts;
import io.jsonwebtoken.signaturealgorithm;
import java.util.date;
import java.util.hashmap;
public class testjwt {
    public static void main(string[] args) {
        testcreatejwt();
        testparsejwt();
    }
    public static void testcreatejwt() {
        jwtbuilder builder = jwts.builder()
                .setid("404")                   // 设置唯一编号
                .setsubject("邢立豹")            // 设置主题 可以是json数据
                .setissuedat(new date())        // 设置签发日期
                // .setexpiration(new date())      // 设置过期时间
                // 设置签名 使用hs256算法 并设置secretkey(字符串)
                .signwith(signaturealgorithm.hs256, "lichun");
        hashmap<string, object> userinfo = new hashmap<>();
        userinfo.put("name","枯木何日可逢春");
        userinfo.put("age", "21");
        builder.addclaims(userinfo);
        system.out.println(builder.compact());
    }
    public static void testparsejwt() {
        string str = "eyjhbgcioijiuzi1nij9.eyjqdgkioii0mdqilcjzdwiioilpgqlnq4vosbkilcjpyxqioje2mza2odazntmsimv4cci6mtyzmdy4mdm1mywibmftzsi6iuaer-acqos9leaxpewpr-maouaypsisimfnzsi6ijixin0.59i5xflz9a-wtoji9kxkf7zqp4zslewrc5dylcy_akc";
        claims claims = jwts.parser()
                .setsigningkey("lichun")
                .parseclaimsjws(str)
                .getbody();
        system.out.println(claims);
    }
}

5. jwt工具类

package com.lichun.utils;
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 {
    // 有效期
    public static final long jwt_ttl = 3600000l;
    // jwt令牌信息
    public static final string jwt_key = "lichun";
    public static string createjwt(string id, string subject, long ttlmillis) {
        signaturealgorithm signaturealgorithm = signaturealgorithm.hs256;
        long nowmillis = system.currenttimemillis();
        date now = new date(nowmillis);
        if (ttlmillis == null) {
            ttlmillis = jwt_ttl;
        }
        long expmillis = nowmillis + ttlmillis;
        date expdate = new date(expmillis);
        secretkey secretkey = generalkey();
        jwtbuilder builder = jwts.builder()
                .setid(id)                      // 设置唯一编号
                .setsubject(subject)            // 设置主题 可以是json数据
                .setissuer("admin")
                .setissuedat(now)               // 设置签发日期
                .setexpiration(expdate)         // 设置过期时间
                // 设置签名 使用hs256算法 并设置secretkey(字符串)
                .signwith(signaturealgorithm.hs256, secretkey);
        return builder.compact();
    }
    /**
     * 生成加密secretkey
     * @return
     */
    public static secretkey generalkey() {
        byte[] encodedkey = base64.getencoder().encode(jwt_key.getbytes());
        secretkey key = new secretkeyspec(encodedkey, 0, encodedkey.length, "aes");
        return key;
    }
    /**
     * 解析令牌数据
     */
    public static claims parsejwt(string jwt) throws exception {
        secretkey secretkey = generalkey();
        return jwts.parser()
                .setsigningkey(secretkey)
                .parseclaimsjws(jwt)
                .getbody();
    }
}

以上就是如何使用jjwt及jwt讲解和工具类的详细内容,更多关于jwt讲解与jjwt使用的资料请关注其它相关文章!