问题描述
我们正在使用 spring-security 5.2 通过 JWT 验证来保护我们的 REST API.
We are using spring-security 5.2 for securing our REST API through JWT validation.
使用 spring:security:oauth2:resourceserver:jwt:jwk-set-uri
属性,我们指示远程 JWKS 端点转换成 Spring 根据这个 URI 创建一个 NimbusJwtDecoder.再往下,创建一个 RemoteJWKSet 对象,该对象缓存对 JWKS 端点的调用,默认 TTL 为 5 分钟.
With the spring:security:oauth2:resourceserver:jwt:jwk-set-uri
property we indicate the remote JWKS endpoint whichtranslates into Spring creating a NimbusJwtDecoder based on this URI.Further down, a RemoteJWKSet object is created that caches the calls to the JWKS endpoint with a default TTL to 5 minutes.
有没有办法增加这个 TTL 来最小化远程调用?也许在具有不同 TTL 的某处注入一个新的 DefaultJWKSetCache
实例?将它尽可能长时间地保存在缓存中似乎是安全的,因为当我们收到一个带有未知孩子的令牌时,将恢复对 JWKS 端点的调用以更新密钥集.
Is there a way to increase this TTL to minimise the remote calls ?Maybe injecting a new DefaultJWKSetCache
instance somewhere with a different TTL ?It seems safe to keep this in cache for as long as possible because when we receive a token with an unknown kid, the call to the JWKS endpoint will be resumed to update the key set.
获取密钥的调用栈如下
JwtAuthenticationProvider
public Authentication authenticate(Authentication authentication)
...
jwt = this.jwtDecoder.decode(bearer.getToken())
...
o.s.security.oauth2.jwt.NimbusJwtDecoder
public Jwt decode(String token)
...
Jwt createdJwt = createJwt(token, jwt);
...
private Jwt createJwt(String token, JWT parsedJwt)
...
JWTClaimsSet jwtClaimsSet = this.jwtProcessor.process(parsedJwt, null);
....
DefaultJWTProcessor
public JWTClaimsSet process(final JWT jwt, final C context)
...
if (jwt instanceof SignedJWT) {
return process((SignedJWT)jwt, context);
}
...
public JWTClaimsSet process(final SignedJWT signedJWT, final C context)
...
List<? extends Key> keyCandidates = selectKeys(signedJWT.getHeader(), claimsSet, context);
...
private List<? extends Key> selectKeys(final JWSHeader header, final JWTClaimsSet claimsSet, final C context)
....
if (getJWSKeySelector() != null) {
return getJWSKeySelector().selectJWSKeys(header, context);
}
....
JWSVerificationKeySelector
public List<Key> selectJWSKeys(final JWSHeader jwsHeader, final C context)
...
List<JWK> jwkMatches = getJWKSource().get(new JWKSelector(jwkMatcher), context);
...
RemoteJWKSet
public List<JWK> get(final JWKSelector jwkSelector, final C context)
...
JWKSet jwkSet = jwkSetCache.get();
if (jwkSet == null) {
jwkSet = updateJWKSetFromURL();
}
...
DefaultJWKSetCache
public JWKSet get() {
if (isExpired()) {
jwkSet = null; // clear
}
return jwkSet;
}
安全依赖:
+- org.springframework.boot:spring-boot-starter-security:jar:2.2.4.RELEASE:compile
| +- org.springframework.security:spring-security-config:jar:5.2.1.RELEASE:compile
| - org.springframework.security:spring-security-web:jar:5.2.1.RELEASE:compile
+- org.springframework.security:spring-security-oauth2-jose:jar:5.2.2.RELEASE:compile
| +- org.springframework.security:spring-security-core:jar:5.2.1.RELEASE:compile
| - org.springframework.security:spring-security-oauth2-core:jar:5.2.1.RELEASE:compile
+- com.nimbusds:nimbus-jose-jwt:jar:8.8:compile
| +- com.github.stephenc.jcip:jcip-annotations:jar:1.0-1:compile
| - net.minidev:json-smart:jar:2.3:compile (version selected from constraint [1.3.1,2.3])
| - net.minidev:accessors-smart:jar:1.2:compile
| - org.ow2.asm:asm:jar:5.0.4:compile
+- org.springframework.security:spring-security-oauth2-resource-server:jar:5.2.1.RELEASE:compile
推荐答案
我最终做了以下事情:
@Bean
public JwtDecoder jwtDecoder() {
JWSKeySelector<SecurityContext> jwsKeySelector = null;
try {
URL jwksUrl = new URL("https://localhost/.well-known/openid-configuration/jwks");
long cacheLifespan = 500;
long refreshTime = 400;
JWKSetCache jwkSetCache = new DefaultJWKSetCache(cacheLifespan, refreshTime, TimeUnit.MINUTES);
RemoteJWKSet<SecurityContext> jwkSet = new RemoteJWKSet<>(jwksUrl,null,jwkSetCache);
jwsKeySelector = JWSAlgorithmFamilyJWSKeySelector.fromJWKSource(jwkSet);
}
catch (KeySourceException e) {
e.printStackTrace();
}
catch (MalformedURLException e) {
e.printStackTrace();
}
DefaultJWTProcessor<SecurityContext> jwtProcessor = new DefaultJWTProcessor<>();
jwtProcessor.setJWSKeySelector(jwsKeySelector);
return new NimbusJwtDecoder(jwtProcessor);
}
这篇关于如何在 spring-security 5.2 中增加 RemoteJWKSet 缓存 TTL的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!