Jwt 加密 解密 公钥 私钥

1 篇文章 0 订阅
1 篇文章 0 订阅

jwt是我们生成token的首选,我在第一次接触写token时,在网上找了很久,没有找到合适的,不是版本问题,就是残缺不全,很恶心。这篇文章我将jwt生成token的全过程写下,希望对初学者有帮助。

SpringBoot版本
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.10</version>
    </parent>
jdk版本
   <properties>
        <maven.compiler.source>11</maven.compiler.source>
        <maven.compiler.target>11</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>
jwt 所需依赖
    <!--JWT-->
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt-api</artifactId>
            <version>0.11.2</version>
        </dependency>
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt-impl</artifactId>
            <version>0.11.2</version>
        </dependency>
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt-jackson</artifactId>
            <version>0.11.2</version>
        </dependency>
Jwt工具类代码

复制后改成自己的类名就能正常使用。

我用的是私钥加密,公钥解密。

私钥和公钥可以用

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;

import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
import java.util.Date;
import java.util.Map;


/**
 * JWT工具类
 *
 */
public class JWTUtils {

    /**
     * 根据给定的密钥字符串获取私钥对象
     * 该方法主要用于将Base64编码的私钥字符串解码并转换为PrivateKey对象
     *
     * @param key Base64编码的私钥字符串
     * @return 转换后的私钥对象PrivateKey
     * @throws RuntimeException 如果密钥字符串无效或算法不支持,将抛出运行时异常
     */
    private static PrivateKey getPrivateKey(String key) {
        byte[] decode = Base64.getDecoder().decode(key);
        PrivateKey privateKey;
        try {
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            PKCS8EncodedKeySpec keySpecPrivate = new PKCS8EncodedKeySpec(decode);
            privateKey = keyFactory.generatePrivate(keySpecPrivate);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return privateKey;
    }

    /**
     * 根据Base64编码的字符串获取RSA公钥
     *
     * @param key Base64编码的公钥字符串
     * @return 转换后的RSA公钥
     * <p>
     * 注意:该方法使用Base64解码器将输入的字符串解码为字节数组,然后使用KeyFactory和X509EncodedKeySpec
     * 将字节数组转换为PublicKey对象。如果转换过程中发生异常,将抛出RuntimeException。
     */
    private static PublicKey getPublicKey(String key) {
        byte[] decode = Base64.getDecoder().decode(key);
        PublicKey publicKey;
        try {
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            X509EncodedKeySpec keySpec = new X509EncodedKeySpec(decode);
            publicKey = keyFactory.generatePublic(keySpec);
        } catch (Exception e) {

            throw new RuntimeException(e);
        }

        return publicKey;
    }


    /**
     * 创建JWT令牌
     *
     * @param subject   要转换为令牌的主题对象,通常是一个包含用户信息的对象
     * @param expMillis 令牌过期时间戳,以毫秒为单位
     * @param key       用于加密令牌的密钥,应保持安全以防止令牌被破解
     * @return 返回生成的JWT令牌字符串
     * <p>
     * 此方法的作用是将一个Java对象(通常包含一些属性和值)转换为一个JWT令牌
     * 它首先将主题对象转换为Map形式,这样可以更容易地将对象的属性和值包含在令牌中
     * 然后使用JWT工具类的createToken方法,将Map和密钥作为参数,生成并返回JWT令牌
     */
    public static String createToken(Object subject, Long expMillis, String key) {
        String data = JSONUtils.toJsonStr(subject);
        long nowMillis = System.currentTimeMillis();
        // 有效期
        Date expDate = new Date(expMillis);
        // 唯一的ID
        String uuid = String.valueOf(IdUtils.getSnowflake().nextId());
        // 签发时间
        Date now = new Date(nowMillis);

        return Jwts.builder()
                .setId(uuid)
                .setSubject(data)
                .setIssuer("xxx-xxx") //发行人
                .setIssuedAt(now)
                .setExpiration(expDate)
                .signWith(getPrivateKey(key))
                .compact();
    }

    /**
     * 解析JWT令牌,获取其中的主体信息
     *
     * @param token 待解析的JWT令牌字符串
     * @param key   用于验证JWT的密钥
     * @return 解析出的JWT主体信息
     */
    public static String parseToken(String token, String key) {
        Claims claims = (Claims) Jwts.parserBuilder()
                .setSigningKey(getPublicKey(key))
                .build()
                .parse(token)
                .getBody();
        return claims.getSubject();
    }

    /**
     * 验证Token(Jwt)的有效性
     *
     * @param token 待验证的Token字符串
     * @param key   用于解码Token的密钥
     * @return 如果Token有效返回true,否则返回false
     */
    public static Boolean verifyToken(String token, String key) {
        // 尝试解析Token,如果解析失败则直接返回false
        String parseToken = null;
        try {
            parseToken = parseToken(token, key);
        } catch (Exception e) {
            return false;
        }

        // 如果Token解析成功,将其转换为Map对象以便检查过期时间
        if (parseToken != null) {
            Map<String, Object> map = BeanUtils.beanToMap(parseToken);
            String expireTime = map.get("expireTime").toString();
            // 比较Token的过期时间和当前时间,判断Token是否过期
            return Long.parseLong(expireTime) > System.currentTimeMillis();

        }
        return false;
    }
自定义公钥私钥
import java.security.KeyPair;  
import java.security.KeyPairGenerator;  
import java.security.NoSuchAlgorithmException;  
import java.security.interfaces.RSAPrivateKey;  
import java.security.interfaces.RSAPublicKey;  
import java.util.Base64;  
  
public class RSAGenerator {  
  
    public static void generateKey() throws NoSuchAlgorithmException {  
        // 初始化密钥对生成器  
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");  
        keyPairGenerator.initialize(2048); // 设置密钥大小为2048位  
  
        // 生成密钥对  
        KeyPair keyPair = keyPairGenerator.generateKeyPair();  
  
        // 提取公钥和私钥  
        RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();  
        RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();  
  
        // 将公钥和私钥转换为字符串  
        String publicKeyString = getPublicKeyAsString(publicKey);  
        String privateKeyString = getPrivateKeyAsString(privateKey);  
  
        System.out.println("Public Key: " + publicKeyString);  
        System.out.println("Private Key: " + privateKeyString);  
    }  
  
    public static String getPublicKeyAsString(RSAPublicKey publicKey) {  
        byte[] encoded = publicKey.getEncoded();  
        return Base64.getEncoder().encodeToString(encoded);  
    }  
  
    public static String getPrivateKeyAsString(RSAPrivateKey privateKey) {  
        byte[] encoded = privateKey.getEncoded();  
        return Base64.getEncoder().encodeToString(encoded);  
    }  
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值