JJWT三种算法的工具类实现

前言

      最近学习jwt生成token,一直各种报错,不知道怎么生成对应的秘钥。周末研究了一下,把jjwt的HMAC、RSA、ECDSA三种签名算法方式都实现了,并记录下来。

依赖版本如下:

<!-- jwt -->
<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt-api</artifactId>
    <version>0.11.5</version>
</dependency>
<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt-impl</artifactId>
    <version>0.11.5</version>
    <scope>runtime</scope>
</dependency>
<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt-jackson</artifactId>
    <version>0.11.5</version>
    <scope>runtime</scope>
</dependency>

一、Hmac方式

1.秘钥
(1)秘钥生成
// 签名算法
SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS512;
// HS256、HS384、HS512生成秘钥的方式
SecretKey secretKey = io.jsonwebtoken.security.Keys.secretKeyFor(signatureAlgorithm);
String secretKeyStr = Base64.getEncoder().encodeToString(secretKey.getEncoded());
System.out.println(secretKeyStr);
Keys.hmacShaKeyFor(Base64.getDecoder().decode(secretKeyStr));
(2)秘钥解析
public static SecretKey generalKey() {
    //调用base64中的getDecoder方法获取解码器,调用解码器中的decode方法将明文密钥进行编码
    byte[] decodeKey = Base64.getDecoder().decode(JWT_KEY);
    SecretKey secretKey = Keys.hmacShaKeyFor(decodeKey);
    //返回加密后的密钥
    return secretKey;
}
2.工具类实现
package com.ykq.shiro.utils;

import cn.hutool.jwt.JWTHeader;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.security.Keys;

import javax.crypto.SecretKey;
import java.util.Base64;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * @author: ykq
 * @date: 2023/2/18 15:27
 * @Description: jwt工具类
 */
public class JwtHmacUtil {
    //定义默认有效期为10分钟 单位:毫秒
    public static final Long JWT_Default_Expires = 10 * 60 * 1000L;

    // 设置HS512密钥
    public static final String JWT_KEY = "tNTaMC1B0Kzdl1q0LKJy7MooRbuwaebz+wSb498OoxoUKL8Yib1P2psiudzuL3S/rGWBGzfcS3nGOsPAoSvt3w==";

    //签发者
    public static final String Issuer = "ykq";

    // 签名算法
    public static final SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS512;

    /**
     * 创建一个token
     */
    public static String createHmacJWT(String id, String subject, Long exprieTime) {
        //创建我们将要使用的JWT签名算法对(token)令牌进行签名
        //获取当前时间并转换为date对象
        long nowMillis = System.currentTimeMillis();

        //签发时间
        Date now = new Date(nowMillis);

        //exprieTime判断用户是否需要设置token有效时间
        if (exprieTime == null) {
            //如果为空,将默认有效期赋值给exprieTime
            exprieTime = JWT_Default_Expires;
        }

        //结束时间 = 当前时间 + 设定的有效期时间
        Long expiresTime = nowMillis + exprieTime;
        //转换为date数据类型
        Date date = new Date(expiresTime);

        JwtBuilder builder = Jwts.builder()
                .setHeaderParam(JWTHeader.TYPE, "JWT")    //一下两行就是Header
                .setHeaderParam(JWTHeader.ALGORITHM, signatureAlgorithm.getValue())
                .setId(id)
                .setSubject(subject) //主题,可以是json数据
                .setIssuer(Issuer)   //签发者
                .setIssuedAt(now)   //签发时间
                .signWith(generalKey(), signatureAlgorithm) //使用ES256对称加密算法签名
                .setExpiration(date);   //设置过期时间

        //compact:规则构建JWT并将其序列化为紧凑的URL安全字符串
        return builder.compact();
    }

    /**
     * 创建一个token
     */
    public static String createHmacJWT(Map<String, Object> claimsMap, Long exprieTime) {
        //创建我们将要使用的JWT签名算法对(token)令牌进行签名
        //获取当前时间并转换为date对象
        long nowMillis = System.currentTimeMillis();

        //签发时间
        Date now = new Date(nowMillis);

        //exprieTime判断用户是否需要设置token有效时间
        if (exprieTime == null) {
            //如果为空,将默认有效期赋值给exprieTime
            exprieTime = JWT_Default_Expires;
        }

        //结束时间 = 当前时间 + 设定的有效期时间
        Long expiresTime = nowMillis + exprieTime;
        //转换为date数据类型
        Date date = new Date(expiresTime);

        JwtBuilder builder = Jwts.builder()
                .setHeaderParam(JWTHeader.TYPE, "JWT")    //一下两行就是Header
                .setHeaderParam(JWTHeader.ALGORITHM, signatureAlgorithm.getValue())
                .setClaims(claimsMap)
                .setIssuer(Issuer)   //签发者
                .setIssuedAt(now)   //签发时间
                .signWith(generalKey(), signatureAlgorithm) //使用ES256对称加密算法签名
                .setExpiration(date);   //设置过期时间

        //compact:规则构建JWT并将其序列化为紧凑的URL安全字符串
        return builder.compact();
    }

    /**
     * 加密明文密钥
     *
     * @return
     */
    public static SecretKey generalKey() {
        //调用base64中的getDecoder方法获取解码器,调用解码器中的decode方法将明文密钥进行编码
        byte[] decodeKey = Base64.getDecoder().decode(JWT_KEY);
        SecretKey secretKey = Keys.hmacShaKeyFor(decodeKey);
        //返回加密后的密钥
        return secretKey;
    }

    /**
     * 解析jwt
     *
     * @param jwt
     * @return
     */
    //此处当解析不出的时候会抛出异常
    public static Claims parseHmacJWT(String jwt) {
        return Jwts.parserBuilder()//获取jwts的解析器
                .setSigningKey(generalKey())    //设置加密后的密钥进行比对
                .build()
                .parseClaimsJws(jwt)// (jwt)    //解析传入的jwt字符串
                .getBody();     // 拿到claims对象返回
    }

    public static void main(String[] args) {

        // HS256、HS384、HS512生成秘钥的方式
/*        SecretKey secretKey = io.jsonwebtoken.security.Keys.secretKeyFor(signatureAlgorithm);
        String secretKeyStr = Base64.getEncoder().encodeToString(secretKey.getEncoded());
        System.out.println(secretKeyStr);
        Keys.hmacShaKeyFor(Base64.getDecoder().decode(secretKeyStr));*/

        String jwtStr = createHmacJWT("123456", "123456", null);
        Claims claims = parseHmacJWT(jwtStr);
        String subject = claims.getSubject();
        System.out.println(jwtStr + " : " + subject);

        Map<String, Object> claimMap = new HashMap<>();
        claimMap.put("memId", "123456");
        claimMap.put(Claims.SUBJECT, "sub123");
        String jwtStr2 = createHmacJWT(claimMap, null);
        Claims claims2 = parseHmacJWT(jwtStr2);
        String subject2 = claims2.getSubject();
        System.out.println(jwtStr2 + " : " + subject2);
    }
}

二、Rsa方式

1.秘钥
(1)秘钥生成
// 签名算法 family为RSA的
SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.PS512;
KeyPair keyPair = io.jsonwebtoken.security.Keys.keyPairFor(signatureAlgorithm);
PrivateKey privateKey = keyPair.getPrivate();
PublicKey publicKey = keyPair.getPublic();
String privateKeyStr = Base64.getEncoder().encodeToString(privateKey.getEncoded());
String publicKeyStr = Base64.getEncoder().encodeToString(publicKey.getEncoded());
System.out.println(privateKeyStr);
System.out.println("-------------");
System.out.println(publicKeyStr);
(2)秘钥解析
/**
 * 加载私钥
 */
public static PrivateKey generalPrivateKey() throws NoSuchAlgorithmException, InvalidKeySpecException {
    byte[] clear = Base64.getDecoder().decode(JWT_PRIVATE_KEY);
    PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(clear);
    KeyFactory fact = KeyFactory.getInstance("RSA");
    return fact.generatePrivate(keySpec);
}

/**
 * 加载公钥
 */
public static PublicKey generalPublicKey() throws GeneralSecurityException {
    byte[] data = Base64.getDecoder().decode(JWT_PUBLIC_KEY);
    X509EncodedKeySpec spec = new X509EncodedKeySpec(data);
    KeyFactory fact = KeyFactory.getInstance("RSA");
    return fact.generatePublic(spec);
}
2.工具类实现
package com.ykq.shiro.utils;

import cn.hutool.jwt.JWTHeader;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;

import java.security.*;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * @author: ykq
 * @date: 2023/2/18 16:21
 * @Description: jwt工具类
 */
public class JwtRsaUtil {
    //定义默认有效期为10分钟 单位:毫秒
    public static final Long JWT_Default_Expires = 10 * 60 * 1000L;

    //签发者
    public static final String Issuer = "ykq";

    // 签名算法 family为RSA的
    public static final SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.PS512;

    // 设置RS256私钥
    public static final String JWT_PRIVATE_KEY = "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";

    // 设置RS256公钥
    public static final String JWT_PUBLIC_KEY = "MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAm5gNfg6RX8Yg6S0Vx+ACc73a5Fi98LbDOAYJWpK+wQgYsPmRq5jqGGmTm+fu17c9u+rQt6jaDgKuxtD2hRAVqFaCxixtBIfb07KPcZ63c5FlRwHCSFR42uFfNzWYf2KWyVUb51CyQus9lKtOqkwJWbBCB6IwPJlCV++39dZIqoGXla89d9UTAjyDo9Hn1h8LrEVnvYqMvCrU3qIHuQAeTnU4+rBxPf/y+sh6rAF1ED1X568R3jCKHcSLNOga8ZrwnQ7on+GZU3YZ8OfceHJiphsNp4J1+rg5xDlz7mgRbigF4SMB0Q2rWC2F95HMEeDzHqdjK8csjYxbGb3OIjc7lEoOrtoeNOlNkow/XOaP/iFqvKK1PVg4ZdxpQZlIPMblgNmQMrWJT8P8JqHKZKVAVxHOXkrhTpAHHNJxCwXd8gGhUjKl1UoufkKWlrfgfYRQ2RBNco0j088ea1pLf8i8I+7a1RCCakEiJV1ZYsTKLJ3Vv09q15hDKtjRFdTf0er9KNwjn4oADFCWN7F5tdSt8QNo60NpSypXvMrHCAbOXLbIq5InT+2Gle80xaHFMs4IL5Ob7elg+tGJhpM9JDZNbjjuGt0KPSbv7gXiR3C/ZY32ShaIIJohoAUwU5aPabDS3B/e+PhIfxCRUf7Pyq70p0UTkcpyk3ptvnC2cI3licECAwEAAQ==";

    /**
     * 创建一个token
     */
    public static String createRsaJWT(String id, String subject, Long exprieTime) throws InvalidKeySpecException, NoSuchAlgorithmException {
        //创建我们将要使用的JWT签名算法对(token)令牌进行签名
        //获取当前时间并转换为date对象
        long nowMillis = System.currentTimeMillis();

        //签发时间
        Date now = new Date(nowMillis);

        //exprieTime判断用户是否需要设置token有效时间
        if (exprieTime == null) {
            //如果为空,将默认有效期赋值给exprieTime
            exprieTime = JWT_Default_Expires;
        }

        //结束时间 = 当前时间 + 设定的有效期时间
        Long expiresTime = nowMillis + exprieTime;
        //转换为date数据类型
        Date date = new Date(expiresTime);

        JwtBuilder builder = Jwts.builder()
                .setHeaderParam(JWTHeader.TYPE, "JWT")    //一下两行就是Header
                .setHeaderParam(JWTHeader.ALGORITHM, signatureAlgorithm.getValue())
                .setId(id)
                .setSubject(subject) //主题,可以是json数据
                .setIssuer(Issuer)   //签发者
                .setIssuedAt(now)   //签发时间
                .signWith(generalPrivateKey(), signatureAlgorithm) //使用ES256对称加密算法签名
                .setExpiration(date);   //设置过期时间

        //compact:规则构建JWT并将其序列化为紧凑的URL安全字符串
        return builder.compact();
    }

    /**
     * 创建一个token
     */
    public static String createRsaJWT(Map<String, Object> claimsMap, Long exprieTime) throws InvalidKeySpecException, NoSuchAlgorithmException {
        //创建我们将要使用的JWT签名算法对(token)令牌进行签名
        //获取当前时间并转换为date对象
        long nowMillis = System.currentTimeMillis();

        //签发时间
        Date now = new Date(nowMillis);

        //exprieTime判断用户是否需要设置token有效时间
        if (exprieTime == null) {
            //如果为空,将默认有效期赋值给exprieTime
            exprieTime = JWT_Default_Expires;
        }

        //结束时间 = 当前时间 + 设定的有效期时间
        Long expiresTime = nowMillis + exprieTime;
        //转换为date数据类型
        Date date = new Date(expiresTime);

        JwtBuilder builder = Jwts.builder()
                .setHeaderParam(JWTHeader.TYPE, "JWT")    //一下两行就是Header
                .setHeaderParam(JWTHeader.ALGORITHM, signatureAlgorithm.getValue())
                .setClaims(claimsMap)
                .setIssuer(Issuer)   //签发者
                .setIssuedAt(now)   //签发时间
                .signWith(generalPrivateKey(), signatureAlgorithm) //使用ES256对称加密算法签名
                .setExpiration(date);   //设置过期时间

        //compact:规则构建JWT并将其序列化为紧凑的URL安全字符串
        return builder.compact();
    }

    /**
     * 加载私钥
     */
    public static PrivateKey generalPrivateKey() throws NoSuchAlgorithmException, InvalidKeySpecException {
        byte[] clear = Base64.getDecoder().decode(JWT_PRIVATE_KEY);
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(clear);
        KeyFactory fact = KeyFactory.getInstance("RSA");
        return fact.generatePrivate(keySpec);
    }

    /**
     * 加载公钥
     */
    public static PublicKey generalPublicKey() throws GeneralSecurityException {
        byte[] data = Base64.getDecoder().decode(JWT_PUBLIC_KEY);
        X509EncodedKeySpec spec = new X509EncodedKeySpec(data);
        KeyFactory fact = KeyFactory.getInstance("RSA");
        return fact.generatePublic(spec);
    }

    /**
     * 解析jwt
     *
     * @param jwt
     * @return
     */
    //此处当解析不出的时候会抛出异常
    public static Claims parseRsaJWT(String jwt) throws GeneralSecurityException {
        return Jwts.parserBuilder()//获取jwts的解析器
                .setSigningKey(generalPublicKey())    //设置加密后的密钥进行比对
                .build()
                .parseClaimsJws(jwt)// (jwt)    //解析传入的jwt字符串
                .getBody();     // 拿到claims对象返回
    }

    public static void main(String[] args) throws GeneralSecurityException {

        // RSA算法生成秘钥对的方式
/*      KeyPair keyPair = io.jsonwebtoken.security.Keys.keyPairFor(signatureAlgorithm);
        PrivateKey privateKey = keyPair.getPrivate();
        PublicKey publicKey = keyPair.getPublic();
        String privateKeyStr = Base64.getEncoder().encodeToString(privateKey.getEncoded());
        String publicKeyStr = Base64.getEncoder().encodeToString(publicKey.getEncoded());
        System.out.println(privateKeyStr);
        System.out.println("-------------");
        System.out.println(publicKeyStr);*/

        String jwtStr = createRsaJWT("123456", "123456", null);
        Claims claims = parseRsaJWT(jwtStr);
        String subject = claims.getSubject();
        System.out.println(jwtStr + " : " + subject);

        Map<String, Object> claimMap = new HashMap<>();
        claimMap.put("memId", "123456");
        claimMap.put(Claims.SUBJECT, "sub123");
        String jwtStr2 = createRsaJWT(claimMap, null);
        Claims claims2 = parseRsaJWT(jwtStr2);
        String subject2 = claims2.getSubject();
        System.out.println(jwtStr2 + " : " + subject2);
    }
}

三、Ecdsa方式

1.秘钥
(1)秘钥生成
// 签名算法
SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.ES512;
KeyPair keyPair = io.jsonwebtoken.security.Keys.keyPairFor(signatureAlgorithm);
PrivateKey privateKey = keyPair.getPrivate();
PublicKey publicKey = keyPair.getPublic();
String privateKeyStr = Base64.getEncoder().encodeToString(privateKey.getEncoded());
String publicKeyStr = Base64.getEncoder().encodeToString(publicKey.getEncoded());
System.out.println(privateKeyStr);
System.out.println("-------------");
System.out.println(publicKeyStr);
(2)秘钥解析
/**
 * 加载私钥
 */
public static PrivateKey generalPrivateKey() throws NoSuchAlgorithmException, InvalidKeySpecException {
    byte[] clear = Base64.getDecoder().decode(JWT_PRIVATE_KEY);
    PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(clear);
    KeyFactory fact = KeyFactory.getInstance("EC");
    return fact.generatePrivate(keySpec);
}

/**
 * 加载公钥
 */
public static PublicKey generalPublicKey() throws GeneralSecurityException {
    byte[] data = Base64.getDecoder().decode(JWT_PUBLIC_KEY);
    X509EncodedKeySpec spec = new X509EncodedKeySpec(data);
    KeyFactory fact = KeyFactory.getInstance("EC");
    return fact.generatePublic(spec);
}
2.工具类实现
package com.ykq.shiro.utils;

import cn.hutool.jwt.JWTHeader;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;

import java.security.*;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * @author: ykq
 * @date: 2023/2/18 16:38
 * @Description: jwt工具类
 */
public class JwtEcdsaUtil {
    //定义默认有效期为10分钟 单位:毫秒
    public static final Long JWT_Default_Expires = 10 * 60 * 1000L;

    //签发者
    public static final String Issuer = "ykq";

    // 签名算法
    public static final SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.ES512;

    // 设置RS256私钥
    public static final String JWT_PRIVATE_KEY = "MGACAQAwEAYHKoZIzj0CAQYFK4EEACMESTBHAgEBBEIBDQorF/iUFxmGaBF5ywq6qyFDUT3mEXqob4aETRgQrDa4avs1ollZaeY4lm9L3+e2XcT6lP88UZBgJ98rR8iK2lQ=";

    // 设置RS256公钥
    public static final String JWT_PUBLIC_KEY = "MIGbMBAGByqGSM49AgEGBSuBBAAjA4GGAAQBkbf4McjTalaTV43KVsFNSXhhxtc69IIzFV7WSdnxZYU5MXwe9uFCR1RGZMgb4W7FmgjUj5oEOqTX4eMhmryEi+wBi8Ha0zugexJYPZOmArjlZeed+lsIyfGuS2B/Yh67DS2ZYSV0oOvAq6eZ9OGp2Vv/aPtn9w2YPyYvHNEeKjLzP1U=";

    /**
     * 创建一个token
     */
    public static String createEcdsaJWT(String id, String subject, Long exprieTime) throws InvalidKeySpecException, NoSuchAlgorithmException {
        //创建我们将要使用的JWT签名算法对(token)令牌进行签名
        //获取当前时间并转换为date对象
        long nowMillis = System.currentTimeMillis();

        //签发时间
        Date now = new Date(nowMillis);

        //exprieTime判断用户是否需要设置token有效时间
        if (exprieTime == null) {
            //如果为空,将默认有效期赋值给exprieTime
            exprieTime = JWT_Default_Expires;
        }

        //结束时间 = 当前时间 + 设定的有效期时间
        Long expiresTime = nowMillis + exprieTime;
        //转换为date数据类型
        Date date = new Date(expiresTime);

        JwtBuilder builder = Jwts.builder()
                .setHeaderParam(JWTHeader.TYPE, "JWT")    //一下两行就是Header
                .setHeaderParam(JWTHeader.ALGORITHM, signatureAlgorithm.getValue())
                .setId(id)
                .setSubject(subject) //主题,可以是json数据
                .setIssuer(Issuer)   //签发者
                .setIssuedAt(now)   //签发时间
                .signWith(generalPrivateKey(), signatureAlgorithm) //使用ES256对称加密算法签名
                .setExpiration(date);   //设置过期时间

        //compact:规则构建JWT并将其序列化为紧凑的URL安全字符串
        return builder.compact();
    }

    /**
     * 创建一个token
     */
    public static String createEcdsaJWT(Map<String, Object> claimsMap, Long exprieTime) throws InvalidKeySpecException, NoSuchAlgorithmException {
        //创建我们将要使用的JWT签名算法对(token)令牌进行签名
        //获取当前时间并转换为date对象
        long nowMillis = System.currentTimeMillis();

        //签发时间
        Date now = new Date(nowMillis);

        //exprieTime判断用户是否需要设置token有效时间
        if (exprieTime == null) {
            //如果为空,将默认有效期赋值给exprieTime
            exprieTime = JWT_Default_Expires;
        }

        //结束时间 = 当前时间 + 设定的有效期时间
        Long expiresTime = nowMillis + exprieTime;
        //转换为date数据类型
        Date date = new Date(expiresTime);

        JwtBuilder builder = Jwts.builder()
                .setHeaderParam(JWTHeader.TYPE, "JWT")    //一下两行就是Header
                .setHeaderParam(JWTHeader.ALGORITHM, signatureAlgorithm.getValue())
                .setClaims(claimsMap)
                .setIssuer(Issuer)   //签发者
                .setIssuedAt(now)   //签发时间
                .signWith(generalPrivateKey(), signatureAlgorithm) //使用ES256对称加密算法签名
                .setExpiration(date);   //设置过期时间

        //compact:规则构建JWT并将其序列化为紧凑的URL安全字符串
        return builder.compact();
    }

    /**
     * 加载私钥
     */
    public static PrivateKey generalPrivateKey() throws NoSuchAlgorithmException, InvalidKeySpecException {
        byte[] clear = Base64.getDecoder().decode(JWT_PRIVATE_KEY);
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(clear);
        KeyFactory fact = KeyFactory.getInstance("EC");
        return fact.generatePrivate(keySpec);
    }

    /**
     * 加载公钥
     */
    public static PublicKey generalPublicKey() throws GeneralSecurityException {
        byte[] data = Base64.getDecoder().decode(JWT_PUBLIC_KEY);
        X509EncodedKeySpec spec = new X509EncodedKeySpec(data);
        KeyFactory fact = KeyFactory.getInstance("EC");
        return fact.generatePublic(spec);
    }

    /**
     * 解析jwt
     *
     * @param jwt
     * @return
     */
    //此处当解析不出的时候会抛出异常
    public static Claims parseEcdsaJWT(String jwt) throws GeneralSecurityException {
        return Jwts.parserBuilder()//获取jwts的解析器
                .setSigningKey(generalPublicKey())    //设置加密后的密钥进行比对
                .build()
                .parseClaimsJws(jwt)// (jwt)    //解析传入的jwt字符串
                .getBody();     // 拿到claims对象返回
    }

    public static void main(String[] args) throws GeneralSecurityException {

        // Ecdsa算法生成秘钥对的方式
/*        KeyPair keyPair = io.jsonwebtoken.security.Keys.keyPairFor(signatureAlgorithm);
        PrivateKey privateKey = keyPair.getPrivate();
        PublicKey publicKey = keyPair.getPublic();
        String privateKeyStr = Base64.getEncoder().encodeToString(privateKey.getEncoded());
        String publicKeyStr = Base64.getEncoder().encodeToString(publicKey.getEncoded());
        System.out.println(privateKeyStr);
        System.out.println("-------------");
        System.out.println(publicKeyStr);*/

        String jwtStr = createEcdsaJWT("123456", "123456", null);
        Claims claims = parseEcdsaJWT(jwtStr);
        String subject = claims.getSubject();
        System.out.println(jwtStr + " : " + subject);

        Map<String, Object> claimMap = new HashMap<>();
        claimMap.put("memId", "123456");
        claimMap.put(Claims.SUBJECT, "sub123");
        String jwtStr2 = createEcdsaJWT(claimMap, null);
        Claims claims2 = parseEcdsaJWT(jwtStr2);
        String subject2 = claims2.getSubject();
        System.out.println(jwtStr2 + " : " + subject2);
    }
}
  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值