使用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创建解析令牌内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Java8的Optional如何干掉空指针(示例详解)

    Java8的Optional如何干掉空指针(示例详解)

    这篇文章主要介绍了Java8的Optional如何干掉空指针,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-01-01
  • Spring Cloud入门教程之Zuul实现API网关与请求过滤

    Spring Cloud入门教程之Zuul实现API网关与请求过滤

    这篇文章主要给大家介绍了关于Spring Cloud入门教程之Zuul实现API网关与请求过滤的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧。
    2018-05-05
  • 分析java中全面的单例模式多种实现方式

    分析java中全面的单例模式多种实现方式

    单例模式是一种常用的软件设计模式,单例对象的类只能允许一个实例存在。许多时候整个系统只需要拥有一个的全局对象,有利于协调系统整体的行为。比如在某个服务器程序中,该服务器的配置信息存放在一个文件中。本文将介绍它的思想和多种实现方式
    2021-06-06
  • spring jpa设置多个主键遇到的小坑及解决

    spring jpa设置多个主键遇到的小坑及解决

    这篇文章主要介绍了spring jpa设置多个主键遇到的小坑及解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-06-06
  • SpringCloud通过Feign传递List类型参数方式

    SpringCloud通过Feign传递List类型参数方式

    这篇文章主要介绍了SpringCloud通过Feign传递List类型参数方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-03-03
  • SpringBoot整合SpringBoot-Admin实现监控应用功能

    SpringBoot整合SpringBoot-Admin实现监控应用功能

    本文主要介绍如何整合Spring Boot Admin,以此监控Springboot应用,文中有相关的示例代码供大家参考,需要的朋友可以参考下
    2023-05-05
  • Java swing实现音乐播放器桌面歌词字体变色效果

    Java swing实现音乐播放器桌面歌词字体变色效果

    这篇文章主要为大家详细介绍了Java swing实现音乐播放器桌面歌词字体变色效果,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-06-06
  • 利用Java实现在PDF中添加工具提示

    利用Java实现在PDF中添加工具提示

    这篇文章主要介绍了如何通过Java在PDF中添加工具提示,文中的示例代码讲解详细,对我们学习或工作有一定的参考价值,感兴趣的可以学习一下
    2022-01-01
  • linux配置jdk环境变量简单教程

    linux配置jdk环境变量简单教程

    这篇文章主要为大家详细介绍了linux配置jdk环境变量简单教程,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-01-01
  • Java的Shiro框架认证流程详解

    Java的Shiro框架认证流程详解

    这篇文章主要介绍了Java的Shiro框架认证流程详解,Shiro 是一个功能强大和易于使用的安全框架,为开发人员提供一个直观而全面的解决方案的认证,授权,加密,会话管理四大功能,需要的朋友可以参考下
    2024-01-01

最新评论