使用JWT创建解析令牌及RSA非对称加密详解

 更新时间:2023年11月16日 08:29:03   作者:立小研先森  
这篇文章主要介绍了JWT创建解析令牌及RSA非对称加密详解,JWT是JSON Web Token的缩写,即JSON Web令牌,是一种自包含令牌,一种情况是webapi,类似之前的阿里云播放凭证的功能,另一种情况是多web服务器下实现无状态分布式身份验证,需要的朋友可以参考下

依赖

开源依赖pom引用地址

<dependency>
  <groupId>io.github.mingyang66</groupId>
  <artifactId>oceansky-jwt</artifactId>
  <version>4.3.2</version>
</dependency>

一、如何使用Java代码的方式生成RSA非对称秘钥

public class RsaPemCreatorFactory {
    /**
     * 公钥文件名
     */
    private static final String PUBLIC_KEY_FILE = "publicKey.pem";
    /**
     * 私钥文件名
     */
    private static final String PRIVATE_KEY_FILE = "privateKey.pem";
    private static final String publicKeyPrefix = "PUBLIC KEY";
    private static final String privateKeyPrefix = "PRIVATE KEY";
    /**
     * 算法
     */
    public static final String ALGORITHM = "RSA";
    public static void create(String directory) throws NoSuchAlgorithmException, IOException {
        // algorithm 指定算法为RSA
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(ALGORITHM);
        // 指定密钥长度为2048
        keyPairGenerator.initialize(1024);
        // 生成密钥
        KeyPair keyPair = keyPairGenerator.generateKeyPair();
        // 文件夹不存在,则先创建
        Files.createDirectories(Paths.get(directory));
        try (FileWriter writer = new FileWriter(String.join("", directory, PRIVATE_KEY_FILE));
             PemWriter pemWriter = new PemWriter(writer);
             FileWriter pubFileWriter = new FileWriter(String.join("", directory, PUBLIC_KEY_FILE));
             PemWriter pubPemWriter = new PemWriter(pubFileWriter)) {
            pemWriter.writeObject(new PemObject(privateKeyPrefix, keyPair.getPrivate().getEncoded()));
            pubPemWriter.writeObject(new PemObject(publicKeyPrefix, keyPair.getPublic().getEncoded()));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

二、如何创建RSAPublicKey、RSAPrivateKey对象

public class RsaAlgorithmFactory {
    public static final String N = "\n";
    public static final String R = "\r";
    public static final String ALGORITHM = "RSA";

    /**
     * 获取公钥对象
     *
     * @param publicKey 公钥字符串
     * @return 公钥对象
     * @throws InvalidKeySpecException
     * @throws NoSuchAlgorithmException
     */
    public static RSAPublicKey getPublicKey(String publicKey) throws InvalidKeySpecException, NoSuchAlgorithmException {
        if (publicKey == null || publicKey.length() == 0) {
            throw new IllegalArgumentException("非法参数");
        }
        byte[] keyBytes = Base64.getDecoder().decode(publicKey.replace(N, "").replace(R, "").getBytes(StandardCharsets.UTF_8));
        X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
        return (RSAPublicKey) keyFactory.generatePublic(x509KeySpec);
    }

    /**
     * 获取私钥对象
     *
     * @param privateKey 私钥字符串
     * @return 私钥对象
     * @throws NoSuchAlgorithmException
     * @throws InvalidKeySpecException
     */
    public static RSAPrivateKey getPrivateKey(String privateKey) throws NoSuchAlgorithmException, InvalidKeySpecException {
        byte[] keyBytes = Base64.getDecoder().decode(privateKey.replace(N, "").replace(R, "").getBytes(StandardCharsets.UTF_8));
        PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
        return (RSAPrivateKey) keyFactory.generatePrivate(pkcs8KeySpec);
    }
}

三、如何创建解析JWT Token

创建工厂方法:

public class JwtFactory {
    /**
     * 创建JWT Token字符串
     *
     * @param builder   入参
     * @param algorithm 算法
     * @return token字符串
     */
    public static String createJwtToken(JWTCreator.Builder builder, Algorithm algorithm) {
        // header:typ、alg 算法
        return builder.sign(algorithm);
    }

    /**
     * JWT字符串解码后的对象
     *
     * @param jwtToken  令牌
     * @param algorithm 算法
     * @return 解析后的jwt token对象
     */
    public static DecodedJWT verifyJwtToken(String jwtToken, Algorithm algorithm) {
        JWTVerifier jwtVerifier = JWT.require(algorithm).build();
        return jwtVerifier.verify(jwtToken);
    }
}

实际使用案例:

    @Test
    public void test() throws InvalidKeySpecException, NoSuchAlgorithmException {
        RSAPublicKey publicKey = RsaAlgorithmFactory.getPublicKey(publicKey1);

        //Security.addProvider(new BouncyCastleProvider());
        RSAPrivateKey privateKey = RsaAlgorithmFactory.getPrivateKey(privateKey1);
        System.out.println(privateKey.getFormat());
        Map<String, Object> headers = new HashMap<>();
        headers.put("ip", "123.12.123.25.12");
        JWTCreator.Builder builder = JWT.create()
                //JWT唯一标识 jti
                .withJWTId(UUID.randomUUID().toString())
                .withHeader(headers)
                .withClaim("username", "田润叶")
                .withClaim("password", "不喜欢")
                //发布者 iss
                .withIssuer("顾养民")
                //发布时间 iat
                .withIssuedAt(Date.from(LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant()))
                //受众|收件人 aud
                .withAudience("田海民", "孙玉婷")
                //指定JWT在指定时间之前不得接受处理  nbf
                .withNotBefore(Date.from(LocalDateTime.now().plusMinutes(-1).atZone(ZoneId.systemDefault()).toInstant()))
                //JWT的主题 sub
                .withSubject("令牌")
                //JWT的密钥ID(实际未用到),用于指定签名验证的密钥 kid  com.auth0.jwt.algorithms.RSAAlgorithm.verify
                .withKeyId("sd")
                //JWT过期时间 exp
                .withExpiresAt(LocalDateTime.now().plusMinutes(5).atZone(ZoneId.systemDefault()).toInstant());
        String jwtToken = JwtFactory.createJwtToken(builder, Algorithm.RSA256(publicKey, privateKey));
        Assert.assertNotNull(jwtToken);

        DecodedJWT jwt = JwtFactory.verifyJwtToken(jwtToken, Algorithm.RSA256(publicKey, privateKey));
        Assert.assertEquals(jwt.getClaim("username").asString(), "田润叶");
        Assert.assertEquals(jwt.getClaim("password").asString(), "不喜欢");
        Assert.assertEquals(jwt.getHeaderClaim("ip").asString(), "123.12.123.25.12");
        Assert.assertEquals(jwt.getIssuer(), "顾养民");
        Assert.assertEquals(jwt.getAudience().get(0), "田海民");
        Assert.assertEquals(jwt.getAudience().get(1), "孙玉婷");
    }

到此这篇关于使用JWT创建解析令牌及RSA非对称加密详解的文章就介绍到这了,更多相关JWT创建解析令牌内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • springboot整合kaptcha验证码的示例代码

    springboot整合kaptcha验证码的示例代码

    kaptcha是一个很有用的验证码生成工具,本篇文章主要介绍了springboot整合kaptcha验证码的示例代码,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-06-06
  • 使用PageHelper插件实现Service层分页

    使用PageHelper插件实现Service层分页

    这篇文章主要为大家详细介绍了使用PageHelper插件实现Service层分页,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-04-04
  • JDBC自定义连接池过程详解

    JDBC自定义连接池过程详解

    这篇文章主要介绍了JDBC自定义连接池过程详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-02-02
  • Lombok同时使⽤@Data和@Builder踩坑总结

    Lombok同时使⽤@Data和@Builder踩坑总结

    这篇文章主要介绍了Lombok同时使⽤@Data和@Builder踩坑总结,文章围绕主题展开详细的内容介绍,具有一定的参考价值需要的小伙伴可以参考一下,希望对你的学习有所帮助
    2022-05-05
  • Java如何实现N叉树数据结构

    Java如何实现N叉树数据结构

    这篇文章主要介绍了Java如何实现N叉树数据结构问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-05-05
  • SpringCloud-Alibaba-Sentinel-配置持久化策略详解

    SpringCloud-Alibaba-Sentinel-配置持久化策略详解

    这篇文章主要介绍了SpringCloud-Alibaba-Sentinel-配置持久化策略,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-03-03
  • IDEA导入Eclipse项目全过程

    IDEA导入Eclipse项目全过程

    这篇文章介绍了如何将Eclipse项目导入到IntelliJ IDEA,并详细步骤如下:新建一个文件夹,用IntelliJ IDEA打开,将项目导入,等待编译完成,配置项目环境和结构,注意文件夹名称可能不同,配置Tomcat,重新编译项目并启动
    2025-11-11
  • idea 与 maven 使用过程中遇到的问题及解决方案

    idea 与 maven 使用过程中遇到的问题及解决方案

    最近将IDEA 升级到 IntelliJ IDEA 2021.3.2,在将maven项目导入IDEA后,maven build时报异常,这个问题是IntelliJ IDEA 2021.3.2 不兼容导致的,下面小编给大家带来了idea 与 maven 使用过程中遇到的问题及解决方案,感兴趣的朋友一起看看吧
    2022-05-05
  • Java中filter用法完整代码示例

    Java中filter用法完整代码示例

    这篇文章主要介绍了Java中filter用法完整代码示例,分享了浏览器不缓存页面的过滤器,检测用户是否登陆的过滤器等相关实例,小编觉得还是挺不错的,这里分享给大家,需要的朋友可以参考下
    2018-01-01
  • String类的获取功能、转换功能

    String类的获取功能、转换功能

    这篇文章给大家介绍了String类的获取功能:String类的基本获取功能、获取功能的举例子、String类的基本转换功能、转换功能的举例子。具体详情大家参考下本文
    2018-04-04

最新评论