首页 > 解决方案 > 如果我有许多与每个令牌对应的有效公钥,如何控制不同的 JWT?

问题描述

我正在使用 spring security,并且我创建了一个 JWT 检查器。到目前为止,它只检查到期时间。

问题是我暴露了两个不同的 api,调用者也使用不同的公钥/私钥来生成我控制的 jwt(s),这意味着我有两个不同的公钥可以检查对应的 JWT。

只保留一个检查令牌但也在公钥之间切换的功能的最佳方法是什么?

例子 :

public class JwtControlValid {

   @Value("${public.key.A}") // from application.properties
   private String pubKeyA;

   @Value("${public.key.B}")
   private String pubKeyB;

   private RSAPublicKey getPubKey() {
     
       try {
         
         
         KeyFactory kf = KeyFactory.getInstance("RSA");

        //  if(caller A)
        X509EncodedKeySpec keySpecX509 = new X509EncodedKeySpec(Base64.getDecoder().decode(pubKeyA));

        //  if (caller B)
        X509EncodedKeySpec keySpecX509 = new X509EncodedKeySpec(Base64.getDecoder().decode(pubKeyB));


        RSAPublicKey pubKey = (RSAPublicKey) kf.generatePublic(keySpecX509);
          
        return pubKey;
        
       }catch ...

和另一个使用第一个函数来判断 true 或 false 的函数:

public boolean isJwtValid(String jwt) {
    try {

        Jwts.parser().setSigningKey(getPublicKey()).parseClaimsJws(jwt);
        return true;

    } catch ....


    return false;
   

两个公钥都是RSA public keys

有没有一种干净的方法可以根据我收到的 jwt 在公钥之间切换?

标签: spring-securityjwtpublic-key

解决方案


问题是我暴露了两个不同的 api,调用者也使用不同的公钥/私钥来生成我控制的 jwt(s),这意味着我有两个不同的公钥可以检查对应的 JWT。

是的,这是一个问题,不是标准。为每个客户端设置公钥的规模很差,通常不受支持。

开箱即用的 Spring 支持信任单个非对称密钥,但不支持多个,因为这不是标准,我不推荐这种方法。

如果您想支持多个密钥,则应该使用JWKs发行服务公开的多个密钥。

这基本上意味着发行您的令牌的发行者(服务器/服务)有一个端点,所有资源服务器都可以获取验证令牌所需的公钥。

优点是您可以轮换密钥,可以检查多个 JWK,它具有可扩展性和安全性等。

如果您仍然想走我强烈不推荐的路径,那么您可以例如JwtAuthenticationProvider使用其接口实现两个。

您可以通过实施AuthenticationManagerResolver.

我强烈建议您阅读spring security 官方文档中的整个 JWT 流程,并使用Nimbusspring security 中包含的内容,而不是JJwt额外的不需要的依赖项。

我只想包括,编写自定义安全性永远不会好,所需要的只是自定义安全性代码中的一个错误,您的整个安全性可能毫无用处。这就是为什么有标准、RFC 和既定流程的原因。避免自定义安全解决方案。


推荐阅读