如果我有许多与每个令牌对应的有效公钥,如何控制不同的 JWT?

问题描述

我正在使用 spring 安全性,并创建了一个 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 ...

和另一个使用第一个判断真假的函数:

public boolean isJwtValid(String jwt) {
    try {

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

    } catch ....


    return false;
   

两个公钥都是 RSA public keys

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

解决方法

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

是的,这是一个问题,不是标准。为每个客户端设置公钥的效果不佳,通常不受支持。

开箱即用的 Spring 支持 trusting single asymmetric key 但不支持多个,因为这不是标准,我不推荐这种方法。

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

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

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

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

您可以通过实现 AuthenticationManagerResolver 来决定使用哪个。

我强烈建议您阅读整个 JWT flow in the spring security official docs 并使用包含在 Spring Security 中的 Nimbus 而不是 JJwt,后者只是一个额外的不需要的依赖项。

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

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...