如何将 .crt 用于 jwt?

How use .crt for jwt?

我的项目中有oauth2 + jwt授权。

@Component
@RequiredArgsConstructor
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

@Override
protected void configure(HttpSecurity http) throws Exception {
    http
            .cors()
            .and()
            .csrf().disable()
            .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
            .and()
            .exceptionHandling().disable()
            .oauth2ResourceServer(OAuth2ResourceServerConfigurer::jwt);
}
}



@Slf4j
@Configuration
public class JwtConfiguration {


@Value("${app.security.jwt.keystore-location}")
private String keyStorePath;

@Value("${app.security.jwt.keystore-password}")
private String keyStorePassword;

@Value("${app.security.jwt.key-alias}")
private String keyAlias;


@Bean
public KeyStore keyStore() {
    try {
        KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
        InputStream resourceAsStream = Thread.currentThread().getContextClassLoader().getResourceAsStream(keyStorePath);
        keyStore.load(resourceAsStream, keyStorePassword.toCharArray());
        return keyStore;
    } catch (IOException | CertificateException | NoSuchAlgorithmException | KeyStoreException e) {
        log.error("Unable to load keystore: {}", keyStorePath, e);
    }

    throw new IllegalArgumentException("Unable to load keystore");
}

@Bean
public RSAPublicKey jwtValidationKey(KeyStore keyStore) {
    try {
        Certificate certificate = keyStore.getCertificate(keyAlias);
        PublicKey publicKey = certificate.getPublicKey();

        if (publicKey instanceof RSAPublicKey) {
            return (RSAPublicKey) publicKey;
        }
    } catch (KeyStoreException e) {
        log.error("Unable to load private key from keystore: {}", keyStorePath, e);
    }

    throw new IllegalArgumentException("Unable to load RSA public key");
}
@Bean
public JwtDecoder jwtDecoder(RSAPublicKey rsaPublicKey) {
    NimbusJwtDecoder jwtDecoder = NimbusJwtDecoder.withPublicKey(rsaPublicKey).build();
    OAuth2TokenValidator<Jwt> validator = new Validator();
    jwtDecoder.setJwtValidator(validator);

    return jwtDecoder;
}



 class Validator implements OAuth2TokenValidator<Jwt> {
    OAuth2Error error = new OAuth2Error("error", "error description", null);

    @Override
    public OAuth2TokenValidatorResult validate(Jwt jwt) {

            ......
        
            return OAuth2TokenValidatorResult.success();
        
    }
}

}

我遵循示例(https://medium.com/swlh/stateless-jwt-authentication-with-spring-boot-a-better-approach-1f5dbae6c30f)并使用 jks 作为键,在这种情况下一切正常。就我而言,这种使用 jks 的方法不合适,我需要使用 kid.crt。最有意思的是kid是文件名,它和jwtheader中的kid字段匹配。也就是说,从 header 接收到 kid 字段后,我们应该得到一个看起来像 kid.crt 的文件。我不知道如何摆脱 jks 以支持 crt。如何创建这样的.crt?以及如何配置在什么时候用密钥取文件?

jks 我是这样创建的

keytool -genkey -alias jwtsigning -keyalg RSA -keystore keystore.jks -keysize 2048

我的application.properties

app.security.jwt.keystore-password=password
app.security.jwt.key-alias=jwtsigning
app.security.jwt.keystore-location=keys/keystore.jks

依赖关系

    <dependency>
  <groupId>org.springframework.security.oauth</groupId>
  <artifactId>spring-security-oauth2</artifactId>
  <version>2.5.1.RELEASE</version>
</dependency>
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
</dependency>

验证传入 JWT 所需的密钥应来自向您颁发 JWT 的授权服务器。您不会自己创建它,除非您也控制着授权服务器,否则您必须创建一对私钥和 public 密钥。私钥用于签署 JWT,public 密钥应分发给 APIs,以便他们可以验证 JWT。

一个完美的方法是当授权服务器公开一个 JWKS 端点时,您的 API 可以从中下载相关密钥。如果这在您的情况下是不可能的,并且您确实需要密钥文件,那么您应该从管理授权服务器的人那里获取它。然后你可以看看例如此处: 关于如何将 crt 添加到密钥库中。拥有密钥库后,您拥有的代码应该可以工作。