JWT在Java中的使用

一、概述

JSON Web Token (JWT) 是一个开放标准 ( RFC 7519 ),它定义了一种紧凑且自包含的方式,用于在各方之间作为 JSON 对象安全地传输信息。该信息可以被验证和信任,因为它是经过数字签名的。JWT 可以使用秘密(使用HMAC算法)或使用RSAECDSA的公钥/私钥对进行签名

虽然 JWT 可以加密以在各方之间提供保密,但我们将重点关注签名令牌。签名令牌可以验证其中包含的声明的完整性,而加密令牌则对其他方隐藏这些声明。当使用公钥/私钥对对令牌进行签名时,签名还证明只有持有私钥的一方才是对其进行签名的一方。

二、使用场景

授权这是使用 JWT 最常见的场景。用户登录后,每个后续请求都将包含 JWT,允许用户访问该令牌允许的路由、服务和资源。单点登录是现在广泛使用 JWT 的一项功能,因为它的开销很小,并且能够轻松地跨不同域使用。

信息交换JSON Web Tokens 是一种在各方之间安全传输信息的好方法。因为 JWT 可以被签名——例如,使用公钥/私钥对——你可以确定发件人就是他们所说的那样。此外,由于使用标头和有效负载计算签名,因此您还可以验证内容是否未被篡改。

三、JWT结构

在其紧凑形式中,JSON Web Tokens 由用点 ( .)分隔的三个部分组成,它们是:

标题

默认情况下标头通常由两部分组成:令牌的类型,即 JWT,以及正在使用的签名算法,例如 HMAC SHA256 或 RSA,也可以在默认的类型和签名算法添加新的信息。

默认生成的头部信息,alg根据使用的签名算法自动生成。

{
  "alg": "HS256",
  "typ": "JWT"
}

可在默认头部信息外添加新的信息

//默认之外添加的新的头部信息
Map<String, Object> stringStringHashMap = new HashMap<>();
stringStringHashMap.put("type","jwt");
stringStringHashMap.put("name","test");
stringStringHashMap.put("time",
        TimestampUtils.getTimestamp(new Date()));
//测试负载部分的数组
Long[] id = new Long[]{1L,2L,3L};
//生成jwt负载信息
String sign = JWT.create()
        //头部信息
        .withHeader(stringStringHashMap)
        //有效载荷
        .withClaim("t1", TimestampUtils.getTimestamp(new Date()))
        .withClaim("t2", TimestampUtils.getTimestamp(new Date()))
        .withClaim("t3", TimestampUtils.getTimestamp(new Date()))
        .withClaim("t4", TimestampUtils.getTimestamp(new Date()))
        .withClaim("t5", TimestampUtils.getTimestamp(new Date()))
        .withClaim("t6", TimestampUtils.getTimestamp(new Date()))
        .withArrayClaim("id", id)
        //签名
        .sign(hhhh);

有效载荷

令牌的第二部分是负载,说白了就是我们要放用户的一些非敏感信息。

//默认之外添加的新的头部信息
Map<String, Object> stringStringHashMap = new HashMap<>();
stringStringHashMap.put("type","jwt");
stringStringHashMap.put("name","test");
stringStringHashMap.put("time",
        TimestampUtils.getTimestamp(new Date()));
//测试负载部分的数组
Long[] id = new Long[]{1L,2L,3L};
//生成jwt负载信息
String sign = JWT.create()
        //头部信息
        .withHeader(stringStringHashMap)
        //有效载荷
        .withClaim("t1", TimestampUtils.getTimestamp(new Date()))
        .withClaim("t2", TimestampUtils.getTimestamp(new Date()))
        .withClaim("t3", TimestampUtils.getTimestamp(new Date()))
        .withClaim("t4", TimestampUtils.getTimestamp(new Date()))
        .withClaim("t5", TimestampUtils.getTimestamp(new Date()))
        .withClaim("t6", TimestampUtils.getTimestamp(new Date()))
        .withArrayClaim("id", id)
        //签名
        .sign(hhhh);

签名

要创建签名部分,必须获取jwt的头部、有效载荷、密钥加上指定的算法,并对其进行签名。

因此,JWT 通常如下所示。

xxxxx.yyyyy.zzzzz

eyJuYW1lIjoidGVzdCIsInR5cCI6IkpXVCIsInRpbWUiOjE2Mjg0MjMxOTUzOTUsInR5cGUiOiJqd3QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6WzEsMiwzXX0.s5_2UOEvNvd-n3mjB8fIzW0sqwlvLG9xqTGVbF5651M

四、实例演示

jwt的依赖

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

代码 

package com.test.Utils;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.AlgorithmMismatchException;
import com.auth0.jwt.exceptions.InvalidClaimException;
import com.auth0.jwt.exceptions.SignatureVerificationException;
import com.auth0.jwt.exceptions.TokenExpiredException;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;
import org.apache.commons.codec.binary.Base64;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
public class JwtUtils {
    private static final String pwd = "123456";
    //生成jwtToken
    public static String CreateToken(){
        //签名使用的密钥
        Algorithm hhhh = Algorithm.HMAC256(pwd);
        //生成jwt头部信息
        /**
         * 如果不添加头部信息,默认会把添加
         * {
         *   "typ": "JWT",
         *   "alg": "加密类型"
         * }
         */
        Map<String, Object> stringStringHashMap = new HashMap<>();
        stringStringHashMap.put("type","jwt");
        stringStringHashMap.put("name","test");
        stringStringHashMap.put("time",
                TimestampUtils.getTimestamp(new Date()));
        //测试负载部分的数组
        Long[] id = new Long[]{1L,2L,3L};
        //生成jwt负载信息
        String sign = JWT.create()
                .withHeader(stringStringHashMap)
                .withClaim("t1", TimestampUtils.getTimestamp(new Date()))
                .withClaim("t2", TimestampUtils.getTimestamp(new Date()))
                .withClaim("t3", TimestampUtils.getTimestamp(new Date()))
                .withClaim("t4", TimestampUtils.getTimestamp(new Date()))
                .withClaim("t5", TimestampUtils.getTimestamp(new Date()))
                .withClaim("t6", TimestampUtils.getTimestamp(new Date()))
                .withArrayClaim("id", id)
                .sign(hhhh);
        return sign;
    }
    //验证jwt
    public static void verify(String jwtStr){
        JWTVerifier build = JWT.require(Algorithm.HMAC256(pwd)).build();
        try{
            //验签
            DecodedJWT verify = build.verify(jwtStr);
            System.out.println("完整的token");
            System.out.println(verify.getToken());
            System.out.println("头部信息");
            System.out.println(verify.getHeader());
            System.out.println("负荷信息");
            System.out.println(verify.getPayload());
            System.out.println("签名信息");
            System.out.println(verify.getSignature());
            //获取主体对应信息
            System.out.println("获取主体对应信息");
            byte[] bytes = Base64.decodeBase64(verify.getPayload());
            System.out.println(new String(bytes));
            System.out.println("获取头部信息");
            byte[] bytes1 = Base64.decodeBase64(verify.getHeader());
            System.out.println(new String(bytes1));
            System.out.println("获取签名信息");
            byte[] bytes2 = Base64.decodeBase64(verify.getSignature());
            System.out.println(new String(bytes2));

            //获取所有负荷信息中的所有Claims
            System.out.println("获取所有负荷信息中的所有Claims");
            Map<String, Claim> claims = verify.getClaims();
            //
            Iterator<Map.Entry<String, Claim>> iterator = claims.entrySet().iterator();
            //遍历
            while (iterator.hasNext()) {
                Map.Entry<String, Claim> next = iterator.next();
                System.out.println(next.getKey()+":"+next.getValue().asLong());
            }
            //获取头部信息
            System.out.println(verify.getHeaderClaim("typ").asString());
        }
        catch (AlgorithmMismatchException e){
            //算法错误
            System.out.println("加密算法和解密算法不一致");
        }
        catch (SignatureVerificationException e){
            //验签失败,验签pwd密码错误
            System.out.println("解密密码错误");
        }
        catch (TokenExpiredException e){
            //token过期
            System.out.println("Token过期");
        }
        catch (InvalidClaimException e){
            //获取不到对应的负荷信息
            System.out.println("获取不到对应的负荷信息");
        }
    }
    public static void main(String[] args) {
        String token = CreateToken();
        System.out.println(token);
        verify(token);
    }
}

五、jwt官网地址 

https://jwt.io/introduction

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值