JJWT三种算法的工具类实现

2023-10-26

前言

      最近学习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);
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

JJWT三种算法的工具类实现 的相关文章

  • JWT:slim v3 和 Android 中的身份验证

    我正在使用 Slim 框架将 JSON 返回到我的 Android 设备 我目前正在我的设备上登录 我使用 3 种不同的方式登录 Facebook Google 和帐户登录 当他进行帐户登录时 他可以注册一个新帐户或使用现有帐户登录 为了我
  • Erlang - 导入 GPG 公钥

    我正在尝试在 Erlang 中做一些与公钥相关的事情 它们要求我跟踪公钥 根据这一页 http www erlang org doc apps public key using public key html id61611 我应该能够通过
  • 如何在 Python 中使用 PKCS12 对 RSA 密钥进行编码?

    我正在使用 Python 在 Google App Engine 下 并且我有一些需要以 PKCS 12 格式导出的 RSA 私钥 有什么可以帮助我的吗 我正在使用 PyCrypto KeyCzar 并且我已经弄清楚如何以 PKCS8 格式
  • 仅使用 RSA 和 AES 构建 openssl

    我正在一个项目中使用 libcrypto a OpenSSL 默认情况下 所有算法都在 libcrypto a 下可用 对于该项目 我只需要 RSA AES 和 SHA 如何仅使用这些算法构建 libcrypto a 如果您通过运行以下命令
  • ASP.NET Core API 在 React 客户端调用时返回 401

    我正在开发一个带有 React Redux 前端的全新 ASP NET Core 2 1 SPA 应用程序 我已经实施了jwt从 Azure AD B2C 获取其令牌的身份验证 当我分析对后端 API 调用的网络选项卡时 我看到令牌被放置在
  • 无法使用 RS256 验证 JWT - 算法无效

    我正在尝试将 JWT Auth 从秘密短语移至 RS256 这是示例代码 import fs from fs import jwt from jsonwebtoken const private key fs readFileSync pr
  • 如何在 Webpack 5 中为 jsonwebtoken 填充缓冲区

    我正在升级到 Webpack 5 并且 jsonwebtoken 包存在问题 https github com auth0 node jsonwebtoken https github com auth0 node jsonwebtoken
  • 在 Android 中解密从 .net 生成的 RSA 加密值

    我在这里浏览了很多帖子 但没有找到正确的解决方案 我想从 Android 解密在 c net 中加密的值 我已使用以下代码片段在 net平台中成功解密 public static void Main string privateKey Ba
  • res.cookie未在浏览器中设置cookie

    我目前正在尝试使用 React 客户端设置 Node Express 应用程序以与之交互 我设置了护照来处理 JWT 身份验证 当用户登录时 我验证电子邮件 密码 然后我设置cookie res cookie jwt token httpO
  • 直接从令牌获取 JWT 声明,ASP Net Core 2.1

    我正在开发 ASP Net Core 2 1 Web API 我已经在我的项目中成功实施了 JWT 有了授权一切都可以正常工作 通常 当我需要用户声明时 我知道我可以这样获取它们 例如电子邮件声明 var claimsIdentity Us
  • AzureAD JWT 令牌受众声明前缀使 JWT 令牌无效

    我正在使用 adal node npm 包通过 AzureAD 进行身份验证 一切正常 我得到了一个令牌 但是 在检查 JWT 令牌中的 aud 声明时 我看到受众 GUID 的前缀为 spn 我认为当我尝试在现有的 Web API 上使用
  • 健全性检查 SSH 公钥? [关闭]

    Closed 这个问题是无关 help closed questions 目前不接受答案 我已要求用户提供他们的公共 id rsa pub ssh 密钥 然后将其放入 home theiraccount ssh authorized key
  • JJWT依赖混乱

    我继承了一个java项目 在POM xml中有这个
  • Jwt 令牌是唯一的

    我正在使用 JWT 网络令牌系统 我能够成功生成令牌 我在 Laravel 中创建 JWT 令牌 如下所示 我正在使用以下技术堆栈 拉拉维尔 5 2 http laravel com 框架 JWT 包裹 https github com t
  • C# 中加密的数据太长,无法在 Java 中解密

    我有一个用 Java 编写的服务器 它在将其发送到客户端之前将其 RSA 密钥转换为 NET 使用的 XML 格式 public String getPublicKeyXML try KeyFactory factory KeyFactor
  • 在 JWT Laravel 中使用授权标头时获取 token_not_provided

    I read 本教程 http blog nedex io create an api server for mobile apps using laravel 5 1 我设法使它完美地工作 唯一的问题是当我从 令牌 token here
  • IssuerSigningKeyResolver 调用异步方法

    我们使用 IssuerSigningKeyResolver 它是 Microsoft IdentityModel Tokens 的一部分 用于令牌验证并接受非异步委托 我们调用一个异步方法 这将导致阻塞调用 因此想知道使用它的正确方法是什么
  • 令牌签名无效错误

    我抛出了这个错误 com auth0 jwt exceptions SignatureVerificationException 使用算法验证时令牌的签名无效 HmacSHA256 private static String SECRET
  • 如何在没有 x5c 的情况下验证来自 jwks 的 JWT 签名

    我有一个 JWT 安全令牌 需要通过 jwks 端点进行验证 jwks 中的数据如下所示 keys kty RSA e AQAB use sig alg RS256 n kid 2132132 b1e6 47e7 a30f 1831942f
  • 使用 secp256r1 曲线和 SHA256 算法生成 ECDSA 签名 - BouncyCastle

    我正在尝试使用带有 secp256r1 曲线 P256 的 ECDSA 和用于消息哈希的 SHA256 算法生成签名 我也在使用 Bouncy Castle 库 下面的代码 public class MyTest param args pu

随机推荐

  • c++仿函数 functor

    内容整理自国外C 教材 先考虑一个简单的例子 假设有一个vector
  • 使用IntelliJ IDEA2018创建并发布一个简单JavaWeb项目

    使用IntelliJ IDEA2018创建并发布一个JavaWeb项目 新建Web项目 Fill New Project 进入创建项目窗口 Java Enterprise 勾选Web Application next 设置项目名及项目路径
  • glsl vscode写_学会用好 Visual Studio Code

    Visual Studio Code是个牛逼的编辑器 启动非常快 完全可以用来代替其他文本文件编辑工具 又可以用来做开发 支持各种语言 相比其他IDE 轻量级完全可配置还集成Git感觉非常的适合前端开发 是微软亲生的想必TypeScript
  • 13个超强的 SpringBoot 实战项目 (还不赶紧收藏起来)

    在GItHub和Gitee上找了一些超好的Spring boot项目 如果大家觉得不错 可以顺手给这些项目点个小星星 一 云收藏 云收藏是一个使用 Spring Boot 构建的开源网站 可以让用户在线随时随地收藏的一个网站 在网站上分类整
  • java使用WebSocket实现一对一实时对话

    最近的项目中有实时对话的需求 这里也是查阅了很多的资料 使用webSocket实现一对一对话是最多的 链接 https pan baidu com s 1Vn1e1qw7nRnU1 4R 4fcGg 提取码 qwer 逻辑讲解 现在我们要给
  • Linux下protobuf的简单使用

    1 创建proto文件 touch test proto 2 往proto文件添加内容 syntax proto3 message Person string name 1 int32 age 18 第一行表示使用proto3语法进行编译
  • 【CUDA入门笔记】CUDA内核与线程配置

    1 CUDA核函数 在GPU上调用的函数成为CUDA核函数 Kernel function 核函数会被GPU上的多个线程执行 每个线程都会执行核函数里的代码 当然由于线程编号的不同 执行的代码路径可能会有所不同 1 函数的最前面是声明标识符
  • Qt进程和线程之一:运行一个进程和进程间通信

    Qt提供了一个与平台无关的QProcess类 用以对进程的支持 本节讲述了怎样在Qt应用程序中启动一个外部程序进程 以及几种常用的进程间通信方法 设计应用程序时 有时不希望将一个不太相关的功能集成到程序中 或者是因为该功能与当前设计的应用程
  • pinia简介和setup语法糖

    pinia简介和setup语法糖 1 pinia的基本特点 pinia同样是一个Vue 状态管理工具 它和vuex有很多相似的地方 本质上他是vuex团队核心成员开发的 在vuex上面提出了一些改进 与vuex相比 pinia去除了vuex
  • Linux的Shell变量、环境变量、代理设置

    Linux的Shell变量 环境变量 代理设置 引言 一 shell与shell变量 环境变量 1 1 概念 1 2 作用域 1 3 SSH 连接 Linux 服务器的环境变量处理流程 1 4 环境变量文件 二 变量增删改查 2 1 查看变
  • 金融tag对照表

    tag 说明 格式 长度 值 描述 4F 应用标识符 AID b 注册应用提供商标识 RID 和专用标识符扩展 A000000333010101A000000333确定UICS注册应用提供商 所有的卡片都一样 010101表明UICS借记应
  • Axios post请求

    1 常见post请求种类 1 form表单提交 method post 是同步的 要素 页面是否刷新 2 axios post 异步操作 1 1axios post请求入门案例 1 1 1编辑前端JS h1 Axios测试案例 2 h1
  • MySQL——使用mysqldump命令备份

    使用mysqldump命令备份 mysqldump命令可以将数据库中的数据备份成一个文本文件 表的结构和表中的数据将存储在生成的文本文件中 本节将介绍mysqldump命令的工作原理和使用方法 mysqldump命令的工作原理很简单 它先查
  • java基础面试题系列(81-90)

    请你说明ConcurrentHashMap有什么优势 1 7和1 8有什么区别 参考链接 https www cnblogs com like minded p 6805301 html 请你说明一下TreeMap的底层结构 TreeMap
  • 第十篇 -- Windows 下免费的GIF录制工具

    网址 https blog csdn net u013019701 article details 80550411 本人用的第二个 亲测好用 转载于 https www cnblogs com smart zihan p 11461101
  • [CISCN2019 华北赛区 Day2 Web1]Hack World

    1 测试过滤 我想到到了 联合注入 unin被过滤 报错注入 and or updatexml被过滤 bool注入和time注入 and or被过滤 可以通过fuzz测试 模糊测试 发现哪些字符被过滤了 length为482的 全都是被过滤
  • LLVM编译流程

    LLVM概述 LLVM是构架编译器 compliter 的框架系统 以C 编写而成 用于优化以任意程序语言编写的程序的便是时间 compile time 链接时间 link time 运行时间 run time 以及空闲时间 idle ti
  • 网络编程--TCP/IP协议

    参考 https lijie blog csdn net article details 105297532 https blog csdn net qq 20785973 article details 83104695 https bl
  • 华为OD机试 - 分苹果(Python)

    题目描述 A B两个人把苹果分为两堆 A希望按照他的计算规则等分苹果 他的计算规则是按照二进制加法计算 并且不计算进位 12 5 9 1100 0101 9 B的计算规则是十进制加法 包括正常进位 B希望在满足A的情况下获取苹果重量最多 输
  • JJWT三种算法的工具类实现

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