Spring Security OAuth 2.0 资源服务器— JWT

目录

一、JWT的最小依赖

二、JWT的最基本配置

1、指定授权服务器

2、初始预期(Startup Expectations)

3、运行时预期(Runtime Expectations)

三、JWT认证是如何工作的

四、直接指定授权服务器 JWK Set Uri

五、提供 audiences

六、覆盖或取代启动自动配置

1、使用jwkSetUri()

2、使用decoder()

3、暴露一个JwtDecoder@Bean

七、配置受信任的算法

1、通过Spring Boot实现

2、使用 Builder

3、来自 JWK Set 的响应

八、信任单一非对称密钥

1、通过 Spring Boot 实现

2、使用 Builder

九、信任单一对称密钥

十、配置 Authorization(授权)

1、手动提取权限

十一、配置验证

1、自定义时间戳验证

2、配置自定义验证器(Validator)

十二、配置 Claim 集映射

1、定制单一 Claim 的转换

2、添加 Claim

3、删除 Claim

4、重命名 Claim

5、配置超时


一、JWT的最小依赖

大多数资源服务器支持被收集到 spring-security-oauth2-resource-server 中。然而,对JWT的解码和验证的支持是在 spring-security-oauth2-jose 中,这意味着为了拥有一个支持JWT编码的 Bearer Token 的工作资源服务器,两者都是必要的。

二、JWT的最基本配置

在使用 Spring Boot 时,将一个应用程序配置为资源服务器包括两个基本步骤。首先,包括所需的依赖,其次,指定授权服务器的位置。

1、指定授权服务器

在Spring Boot应用程序中,要指定使用哪一个授权服务器,只需:

spring:security:oauth2:resourceserver:jwt:issuer-uri: https://idp.example.com/issuer

其中 idp.example.com/issuer,是授权服务器将发出的JWT令牌的 iss claim 中包含的值。资源服务器将使用这个属性来进一步自我配置,发现授权服务器的公钥,并随后验证传入的 JWT。

要使用 issuer-uri 属性,还必须是 idp.example.com/issuer/.well-known/openid-configuration、idp.example.com/.well-known/openid-configuration/issuer 或 idp.example.com/.well-known/oauth-authorization-server/issuer 中的一个是授权服务器的支持端点。这个端点被称为 提供者配置 端点或 授权服务器元数据 端点。

就这样!

2、初始预期(Startup Expectations)

当使用该属性和这些依赖关系时,资源服务器将自动配置自己以验证JWT编码的Bearer Token。

它通过一个确定性的启动过程来实现这一点。

  1. 查询提供者配置或授权服务器元数据端点的 jwks_url 属性
  2. 查询 jwks_url 端点的支持算法
  3. 配置验证策略,以查询 jwks_url 中找到的算法的有效公钥。
  4. 配置验证策略,根据 idp.example.com,验证每个JWTs iss claim。

这个过程的一个结果是,授权服务器必须启动并接收请求,以便资源服务器成功启动。

如果在资源服务器查询时,授权服务器已经停机(给定适当的超时),那么启动将失败。

3、运行时预期(Runtime Expectations)

一旦应用程序启动,资源服务器将尝试处理任何包含 Authorization: Bearer 头的请求。

GET / HTTP/1.1
Authorization: Bearer some-token-value # Resource Server will process this

只要指定了这个 scheme,资源服务器就会尝试根据 Bearer Token 规范来处理请求。

给定一个格式良好的JWT,资源服务器将:

  1. 根据启动期间从 jwks_url 端点获得的公钥验证其签名,并与JWT相匹配。
  2. 验证JWT的 exp 和 nbf 时间戳以及JWT的 iss claim。
  3. 将每个 scope 映射到一个前缀为 SCOPE_ 的授权。

随着授权服务器提供新的密钥,Spring Security将自动轮换用于验证JWTs的密钥。

由此产生的 Authentication#getPrincipal 默认为Spring Security Jwt 对象,Authentication#getName 映射到JWT的 sub 属性,如果有的话。

从这里,考虑跳转到:

  • JWT认证是如何工作的
  • 如何在不将资源服务器的启动与授权服务器的可用性挂钩的情况下进行配置
  • 如何在非Spring Boot的情况下进行配置

三、JWT认证是如何工作的

接下来,让我们看看Spring Security用来支持基于servlet的应用程序中的 JWT 认证的架构组件,比如我们刚才看到的那个。

JwtAuthenticationProvider 是一个 AuthenticationProvider 实现,利用 JwtDecoder 和 JwtAuthenticationConverter 来验证JWT。

让我们来看看 JwtAuthenticationProvider 是如何在Spring Security中工作的。图中解释了数字中的 AuthenticationManager 在 读取 Bearer Token时的工作细节。

Figure 1. JwtAuthenticationProvider Usage

读取 Bearer Token 的认证 Filter 将一个 BearerTokenAuthenticationToken 传递给由 ProviderManager 实现的认证管理器。

ProviderManager 被配置为使用一个 JwtAuthenticationProvider 类型的 AuthenticationProvider。

JwtAuthenticationProvider 使用 JwtDecoder 对 Jwt 进行解码、验证和确认。

JwtAuthenticationProvider 然后使用 JwtAuthenticationConverter 将 Jwt 转换为授予权限的集合(Collection )。

当认证成功时,返回的 Authentication 是 JwtAuthenticationToken 类型的,并且有一个 principal 是由配置的 JwtDecoder 返回的 Jwt。最终,返回的 JwtAuthenticationToken 将被认证 Filter 设置在 SecurityContextHolder 上。

四、直接指定授权服务器 JWK Set Uri

如果授权服务器不支持任何配置端点,或者如果资源服务器必须能够独立于授权服务器启动,那么也可以提供 jwk-set-uri。

spring:security:oauth2:resourceserver:jwt:issuer-uri: https://idp.example.comjwk-set-uri: https://idp.example.com/.well-known/jwks.json

JWK Set uri不是标准化的,但通常可以在授权服务器的文档中找到。

因此,资源服务器在启动时将不会ping授权服务器。我们仍然指定了 issuer-uri,这样资源服务器仍然会验证传入的JWT的 iss claim。

This property can also be supplied directly on the DSL.

五、提供 audiences

如前所述,issuer-uri 属性验证了 iss claim;这是谁发送的JWT。

Boot 还具有用于验证 aud claim 的 audiences 属性;这是 JWT 的发送对象。

资源服务器的 audience 可以这样表示:

spring:security:oauth2:resourceserver:jwt:issuer-uri: https://idp.example.comaudiences: https://my-resource-server.example.com

如果需要,你也可以 通过编程添加 aud 验证。

结果是,如果 JWT 的 iss claim 不是 idp.example.com,且其 aud claim 的列表中不包含 my-resource-server.example.com,则验证将失败。

六、覆盖或取代启动自动配置

有两个 @Bean 是Spring Boot代表资源服务器生成的。

第一个是 SecurityFilterChain,它将应用程序配置为资源服务器。当包括 spring-security-oauth2-jose 时,这个 SecurityFilterChain 看起来像:

Default JWT Configuration

  • Java
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {http.authorizeHttpRequests(authorize -> authorize.anyRequest().authenticated()).oauth2ResourceServer((oauth2) -> oauth2.jwt(Customizer.withDefaults()));return http.build();
}

如果应用程序没有公开 SecurityFilterChain Bean,那么Spring Boot将公开上述的默认bean。

替换它就像在应用程序中公开该bean一样简单。

Custom JWT Configuration

  • Java
@Configuration
@EnableWebSecurity
public class MyCustomSecurityConfiguration {@Beanpublic SecurityFilterChain filterChain(HttpSecurity http) throws Exception {http.authorizeHttpRequests(authorize -> authorize.requestMatchers("/messages/**").hasAuthority("SCOPE_message:read").anyRequest().authenticated()).oauth2ResourceServer(oauth2 -> oauth2.jwt(jwt -> jwt.jwtAuthenticationConverter(myConverter())));return http.build();}
}

以上要求任何以 /messages/ 开头的URL的scope为 message:read。

oauth2ResourceServer DSL上的方法也将覆盖或取代自动配置。

例如,Spring Boot 创建的第二个 @Bean 是一个 JwtDecoder,它 将 String token 解码为 Jwt 的验证实例。

JWT Decoder

  • Java
@Bean
public JwtDecoder jwtDecoder() {return JwtDecoders.fromIssuerLocation(issuerUri);
}

调用 JwtDecoders#fromIssuerLocation 就是调用提供者配置或授权服务器元数据端点,以便导出JWK Set Uri。

如果应用程序没有暴露一个 JwtDecoder Bean,那么Spring Boot将暴露上述默认的 JwtDecoder。

它的配置可以用 jwkSetUri() 重写或用 decoder() 替换。

或者,如果你根本没有使用Spring Boot,那么这两个组件—​filter chain 和 JwtDecoder 都可以用XML指定。

过滤器链(filter chain)是这样指定的。

Default JWT Configuration

  • Java
<http><intercept-uri pattern="/**" access="authenticated"/><oauth2-resource-server><jwt decoder-ref="jwtDecoder"/></oauth2-resource-server>
</http>

而 JwtDecoder 是这样的:

JWT Decoder

  • Java
<bean id="jwtDecoder"class="org.springframework.security.oauth2.jwt.JwtDecoders"factory-method="fromIssuerLocation"><constructor-arg value="${spring.security.oauth2.resourceserver.jwt.jwk-set-uri}"/>
</bean>

1、使用jwkSetUri()

授权服务器的 JWK Set Uri 可以 作为一个配置属性 来配置,也可以在DSL中提供。

JWK Set Uri Configuration

  • Java
@Configuration
@EnableWebSecurity
public class DirectlyConfiguredJwkSetUri {@Beanpublic SecurityFilterChain filterChain(HttpSecurity http) throws Exception {http.authorizeHttpRequests(authorize -> authorize.anyRequest().authenticated()).oauth2ResourceServer(oauth2 -> oauth2.jwt(jwt -> jwt.jwkSetUri("https://idp.example.com/.well-known/jwks.json")));return http.build();}
}

使用 jwkSetUri() 优先于任何配置属性。

2、使用decoder()

比 jwkSetUri() 更强大的是 decoder(),它将完全取代 JwtDecoder 的任何Boot自动配置。

JWT Decoder Configuration

  • Java
@Configuration
@EnableWebSecurity
public class DirectlyConfiguredJwtDecoder {@Beanpublic SecurityFilterChain filterChain(HttpSecurity http) throws Exception {http.authorizeHttpRequests(authorize -> authorize.anyRequest().authenticated()).oauth2ResourceServer(oauth2 -> oauth2.jwt(jwt -> jwt.decoder(myCustomDecoder())));return http.build();}
}

当需要更深入的配置时,如 validation、mapping或request timeouts,这很方便。

3、暴露一个JwtDecoder@Bean

或者,暴露一个JwtDecoder @Bean 与 decoder() 有同样的效果。

你可以像这样用 jwkSetUri 构建一个:

  • Java
@Bean
public JwtDecoder jwtDecoder() {return NimbusJwtDecoder.withJwkSetUri(jwkSetUri).build();
}

或者你可以使用 issuer,并让 NimbusJwtDecoder 在调用 build() 时查找 jwkSetUri,如下所示:

  • Java
@Bean
public JwtDecoder jwtDecoder() {return NimbusJwtDecoder.withIssuerLocation(issuer).build();
}

或者,如果默认值对你有效,你也可以使用 JwtDecoders,除了配置 decoder 的验证器之外,它还可以完成上述工作:

  • Java
@Bean
public JwtDecoders jwtDecoder() {return JwtDecoders.fromIssuerLocation(issuer);
}

七、配置受信任的算法

默认情况下,NimbusJwtDecoder,以及资源服务器,将只信任和验证使用 RS256 的令牌。

你可以通过Spring Boot、NimbusJwtDecoder builder或从 JWK Set response 中定制。

1、通过Spring Boot实现

设置算法的最简单方法是配置一个属性。

spring:security:oauth2:resourceserver:jwt:jws-algorithm: RS512jwk-set-uri: https://idp.example.org/.well-known/jwks.json

2、使用 Builder

不过,为了获得更大的权力,我们可以使用 NimbusJwtDecoder 附带的一个构建器。

  • Java
@Bean
JwtDecoder jwtDecoder() {return NimbusJwtDecoder.withIssuerLocation(this.issuer).jwsAlgorithm(RS512).build();
}

多次调用 jwsAlgorithm 将配置 NimbusJwtDecoder 以信任一种以上的算法,像这样。

  • Java
@Bean
JwtDecoder jwtDecoder() {return NimbusJwtDecoder.withIssuerLocation(this.issuer).jwsAlgorithm(RS512).jwsAlgorithm(ES512).build();
}

或者,你可以调用 jwsAlgorithms。

  • Java
@Bean
JwtDecoder jwtDecoder() {return NimbusJwtDecoder.withIssuerLocation(this.issuer).jwsAlgorithms(algorithms -> {algorithms.add(RS512);algorithms.add(ES512);}).build();
}

3、来自 JWK Set 的响应

由于 Spring Security 的 JWT 支持基于 Nimbus,因此你也可以使用它的所有强大功能。

例如,Nimbus有一个 JWSKeySelector 实现,它将根据JWK Set URI的响应(Response)来选择算法集。你可以用它来生成一个 NimbusJwtDecoder,像这样。

  • Java
@Bean
public JwtDecoder jwtDecoder() {// makes a request to the JWK Set endpointJWSKeySelector<SecurityContext> jwsKeySelector =JWSAlgorithmFamilyJWSKeySelector.fromJWKSetURL(this.jwkSetUrl);DefaultJWTProcessor<SecurityContext> jwtProcessor =new DefaultJWTProcessor<>();jwtProcessor.setJWSKeySelector(jwsKeySelector);return new NimbusJwtDecoder(jwtProcessor);
}

八、信任单一非对称密钥

比用JWK Set端点支持资源服务器更简单的是硬编码一个RSA公钥。公钥可以通过Spring Boot或 使用 Builder来提供。

1、通过 Spring Boot 实现

通过Spring Boot指定一个密钥是非常简单的。密钥的位置可以像这样指定。

spring:security:oauth2:resourceserver:jwt:public-key-location: classpath:my-key.pub

或者,为了能够进行更复杂的查询,你可以用 RsaKeyConversionServicePostProcessor 进行后处理。

  • Java
@Bean
BeanFactoryPostProcessor conversionServiceCustomizer() {return beanFactory ->beanFactory.getBean(RsaKeyConversionServicePostProcessor.class).setResourceLoader(new CustomResourceLoader());
}

指定你的key的位置。

key.location: hfds://my-key.pub

然后自动注入value。

  • Java
@Value("${key.location}")
RSAPublicKey key;

2、使用 Builder

要直接连接一个 RSAPublicKey,你可以简单地使用适当的 NimbusJwtDecoder builder,像这样。

  • Java
@Bean
public JwtDecoder jwtDecoder() {return NimbusJwtDecoder.withPublicKey(this.key).build();
}

九、信任单一对称密钥

使用单一的对称密钥也很简单。你可以简单地加载你的 SecretKey 并使用适当的 NimbusJwtDecoder builder,像这样。

  • Java
@Bean
public JwtDecoder jwtDecoder() {return NimbusJwtDecoder.withSecretKey(this.key).build();
}

十、配置 Authorization(授权)

从OAuth 2.0授权服务器发出的JWT通常会有一个 scope 或 scp 属性,表明它被授予的scope(或权限),例如:

{ …​, "scope" : "messages contacts"}

当出现这种情况时,资源服务器将尝试把这些scope强制性的成一个授予权限的列表,在每个scope前面加上 "SCOPE_" 字符串。

这意味着,要用从JWT派生的scope来保护一个端点或方法,相应的表达式应该包括这个前缀。

Authorization Configuration

  • Java
@Configuration
@EnableWebSecurity
public class DirectlyConfiguredJwkSetUri {@Beanpublic SecurityFilterChain filterChain(HttpSecurity http) throws Exception {http.authorizeHttpRequests(authorize -> authorize.requestMatchers("/contacts/**").hasAuthority("SCOPE_contacts").requestMatchers("/messages/**").hasAuthority("SCOPE_messages").anyRequest().authenticated()).oauth2ResourceServer(OAuth2ResourceServerConfigurer::jwt);return http.build();}
}

或者类似于方法安全(method security)。

  • Java
@PreAuthorize("hasAuthority('SCOPE_messages')")
public List<Message> getMessages(...) {}

1、手动提取权限

然而,在很多情况下,这个默认值是不够的。例如,有些授权服务器并不使用 scope 属性,而是有自己的自定义属性。或者,在其他时候,资源服务器可能需要将属性或属性的构成调整为内部化的授权。

为此,Spring Security提供了 JwtAuthenticationConverter,它负责 将 Jwt 转换为 Authentication。默认情况下,Spring Security会将 JwtAuthenticationProvider 与 JwtAuthenticationConverter 的默认实例连接起来。

作为配置 JwtAuthenticationConverter 的一部分,你可以提供一个附属的转换器,从 Jwt 到授予权限集合(Collection)。

假设你的授权服务器在一个名为 authorities 的自定义 claim 中交流授权。在这种情况下,你可以配置 JwtAuthenticationConverter 应该检查的 claim,像这样。

Authorities Claim Configuration

  • Java
@Bean
public JwtAuthenticationConverter jwtAuthenticationConverter() {JwtGrantedAuthoritiesConverter grantedAuthoritiesConverter = new JwtGrantedAuthoritiesConverter();grantedAuthoritiesConverter.setAuthoritiesClaimName("authorities");JwtAuthenticationConverter jwtAuthenticationConverter = new JwtAuthenticationConverter();jwtAuthenticationConverter.setJwtGrantedAuthoritiesConverter(grantedAuthoritiesConverter);return jwtAuthenticationConverter;
}

你也可以把权限的前缀配置成不同的。你可以像这样把每个权限的前缀改为 ROLE_,而不是用 SCOPE_。

Authorities Prefix Configuration

  • Java
@Bean
public JwtAuthenticationConverter jwtAuthenticationConverter() {JwtGrantedAuthoritiesConverter grantedAuthoritiesConverter = new JwtGrantedAuthoritiesConverter();grantedAuthoritiesConverter.setAuthorityPrefix("ROLE_");JwtAuthenticationConverter jwtAuthenticationConverter = new JwtAuthenticationConverter();jwtAuthenticationConverter.setJwtGrantedAuthoritiesConverter(grantedAuthoritiesConverter);return jwtAuthenticationConverter;
}

或者,你可以通过调用 JwtGrantedAuthoritiesConverter#setAuthorityPrefix("") 完全删除前缀。

为了提高灵活性,DSL支持用任何实现 Converter<Jwt, AbstractAuthenticationToken> 的类来完全替换converter。

  • Java
static class CustomAuthenticationConverter implements Converter<Jwt, AbstractAuthenticationToken> {public AbstractAuthenticationToken convert(Jwt jwt) {return new CustomAuthenticationToken(jwt);}
}// ...@Configuration
@EnableWebSecurity
public class CustomAuthenticationConverterConfig {@Beanpublic SecurityFilterChain filterChain(HttpSecurity http) throws Exception {http.authorizeHttpRequests(authorize -> authorize.anyRequest().authenticated()).oauth2ResourceServer(oauth2 -> oauth2.jwt(jwt -> jwt.jwtAuthenticationConverter(new CustomAuthenticationConverter())));return http.build();}
}

十一、配置验证

使用 最小的Spring Boot配置,表明授权服务器的发行者URI,资源服务器将默认验证 iss claim 以及 exp 和 nbf 时间戳 claim。

在需要定制验证的情况下,资源服务器会提供两个标准的验证器,同时也接受自定义的 OAuth2TokenValidator 实例。

1、自定义时间戳验证

JWT通常有一个有效期,开始时间在 nbf claim 中指出,结束时间在 exp 声明中指出。

然而,每台服务器都可能经历时钟漂移,这可能导致令牌在一台服务器上显示为过期,而在另一台服务器上却不是。随着分布式系统中合作服务器数量的增加,这可能会造成一些实施上的困扰。

资源服务器使用 JwtTimestampValidator 来验证令牌的有效性,它可以配置一个 clockSkew 来缓解上述问题。

  • Java
@Bean
JwtDecoder jwtDecoder() {NimbusJwtDecoder jwtDecoder = (NimbusJwtDecoder)JwtDecoders.fromIssuerLocation(issuerUri);OAuth2TokenValidator<Jwt> withClockSkew = new DelegatingOAuth2TokenValidator<>(new JwtTimestampValidator(Duration.ofSeconds(60)),new JwtIssuerValidator(issuerUri));jwtDecoder.setJwtValidator(withClockSkew);return jwtDecoder;
}

默认情况下,资源服务器配置的时钟偏移为60秒。

2、配置自定义验证器(Validator)

使用 OAuth2TokenValidator API,添加 aud claim 的检查很简单。

  • Java
  • Kotlin
OAuth2TokenValidator<Jwt> audienceValidator() {return new JwtClaimValidator<List<String>>(AUD, aud -> aud.contains("messaging"));
}

或者,为了更多的控制,你可以实现你自己的 OAuth2TokenValidator。

  • Java
static class AudienceValidator implements OAuth2TokenValidator<Jwt> {OAuth2Error error = new OAuth2Error("custom_code", "Custom error message", null);@Overridepublic OAuth2TokenValidatorResult validate(Jwt jwt) {if (jwt.getAudience().contains("messaging")) {return OAuth2TokenValidatorResult.success();} else {return OAuth2TokenValidatorResult.failure(error);}}
}// ...OAuth2TokenValidator<Jwt> audienceValidator() {return new AudienceValidator();
}

然后,为了添加到资源服务器中,只需指定 JwtDecoder 实例即可。

  • Java
@Bean
JwtDecoder jwtDecoder() {NimbusJwtDecoder jwtDecoder = (NimbusJwtDecoder)JwtDecoders.fromIssuerLocation(issuerUri);OAuth2TokenValidator<Jwt> audienceValidator = audienceValidator();OAuth2TokenValidator<Jwt> withIssuer = JwtValidators.createDefaultWithIssuer(issuerUri);OAuth2TokenValidator<Jwt> withAudience = new DelegatingOAuth2TokenValidator<>(withIssuer, audienceValidator);jwtDecoder.setJwtValidator(withAudience);return jwtDecoder;
}

如前所述,你可以在 Boot 中 配置 aud 验证。

十二、配置 Claim 集映射

Spring Security使用 Nimbus 库来解析JWT并验证其签名。因此,Spring Security受制于Nimbus对每个字段值的解释,以及如何将每个字段强制成一个Java类型。

例如,由于Nimbus仍然与Java 7兼容,它不使用 Instant 来表示时间戳字段。

而且,完全可以使用不同的库或用于JWT处理,它可能会做出自己的强制决定,需要进行调整。

或者,很简单,资源服务器可能想出于特定领域的原因从JWT中添加或删除claim。

为了这些目的,资源服务器支持用 MappedJwtClaimSetConverter 映射JWT请求集。

1、定制单一 Claim 的转换

默认情况下,MappedJwtClaimSetConverter 将试图将 claim 强制为以下类型。

Claim

Java 类型

aud

Collection<String>

exp

Instant

iat

Instant

iss

String

jti

String

nbf

Instant

sub

String

可以使用 MappedJwtClaimSetConverter.withDefaults 来配置单个 claim 的转换策略。

  • Java
@Bean
JwtDecoder jwtDecoder() {NimbusJwtDecoder jwtDecoder = NimbusJwtDecoder.withIssuerLocation(issuer).build();MappedJwtClaimSetConverter converter = MappedJwtClaimSetConverter.withDefaults(Collections.singletonMap("sub", this::lookupUserIdBySub));jwtDecoder.setClaimSetConverter(converter);return jwtDecoder;
}

这将保持所有的默认值,除了它将覆盖 sub 的默认 claim converter。

2、添加 Claim

MappedJwtClaimSetConverter 也可以用来添加一个自定义的 claim,例如,为了适应现有的系统。

  • Java
MappedJwtClaimSetConverter.withDefaults(Collections.singletonMap("custom", custom -> "value"));

3、删除 Claim

删除claim也很简单,使用相同的API。

  • Java
MappedJwtClaimSetConverter.withDefaults(Collections.singletonMap("legacyclaim", legacy -> null));

4、重命名 Claim

在更复杂的情况下,如同时咨询多个claim或重命名一个claim,资源服务器接受任何实现 Converter<Map<String, Object>, Map<String,Object>> 的类。

  • Java
public class UsernameSubClaimAdapter implements Converter<Map<String, Object>, Map<String, Object>> {private final MappedJwtClaimSetConverter delegate =MappedJwtClaimSetConverter.withDefaults(Collections.emptyMap());public Map<String, Object> convert(Map<String, Object> claims) {Map<String, Object> convertedClaims = this.delegate.convert(claims);String username = (String) convertedClaims.get("user_name");convertedClaims.put("sub", username);return convertedClaims;}
}

然后,可以像正常一样提供实例。

  • Java
@Bean
JwtDecoder jwtDecoder() {NimbusJwtDecoder jwtDecoder = NimbusJwtDecoder.withIssuerLocation(issuer).build();jwtDecoder.setClaimSetConverter(new UsernameSubClaimAdapter());return jwtDecoder;
}

5、配置超时

默认情况下,资源服务器使用连接和套接字超时30秒来与授权服务器进行协调。

这在某些情况下可能太短了。此外,它没有考虑到更复杂的模式,如退订和发现。

为了调整资源服务器连接到授权服务器的方式,NimbusJwtDecoder 接受了一个 RestOperations 的实例。

  • Java
@Bean
public JwtDecoder jwtDecoder(RestTemplateBuilder builder) {RestOperations rest = builder.setConnectTimeout(Duration.ofSeconds(60)).setReadTimeout(Duration.ofSeconds(60)).build();NimbusJwtDecoder jwtDecoder = NimbusJwtDecoder.withIssuerLocation(issuer).restOperations(rest).build();return jwtDecoder;
}

另外,默认情况下,资源服务器会在内存中缓存授权服务器的JWK集5分钟,你可能想调整一下。此外,它没有考虑到更复杂的缓存模式,如驱逐或使用共享缓存。

为了调整资源服务器缓存JWK集的方式,NimbusJwtDecoder 接受一个 Cache 的实例。

  • Java
@Bean
public JwtDecoder jwtDecoder(CacheManager cacheManager) {return NimbusJwtDecoder.withIssuerLocation(issuer).cache(cacheManager.getCache("jwks")).build();
}

当给定一个 Cache 时,资源服务器将使用JWK Set Uri作为键,JWK Set JSON作为值。

Spring不是一个缓存提供者,所以你需要确保包含适当的依赖关系,比如 spring-boot-starter-cache 和你喜欢的缓存提供者。

无论是套接字还是缓存超时,你可能反而想直接与Nimbus合作。要做到这一点,请记住 NimbusJwtDecoder 有一个构造函数,它接收 Nimbus 的 JWTProcessor。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/180402.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

让SOME/IP运转起来——SOME/IP系统设计(上)

什么是SOME/IP&#xff1f; SOME/IP&#xff08;Scalable service-Oriented MiddlewarE over IP&#xff09;是AUTOSAR应用层的协议&#xff0c;是基于IP协议的面向服务的可拓展性的中间件。 SOME/IP中主要定义了&#xff1a; 数据的序列化&#xff1a;SOME/IP支持的数据类型…

如何通过智能管理箱实现高效文件管理:关键字轻松修改文件名

在信息化时代&#xff0c;文件管理变得尤为重要。智能管理箱已经成为我们生活中不可或缺的一部分。它可以帮助我们高效地管理各种文件&#xff0c;使得我们的工作和生活更加便捷。是一种高效的文件管理工具&#xff0c;可以帮助我们轻松地整理和分类文件&#xff0c;提高工作效…

计算机网络之网络层(全)

网络层的功能 互联网在网络层的设计思路是&#xff0c;向上只提供简单灵活的、无连接的、尽最大努力交付的数据报服务。 路由器在能够开始向输出链路传输分组的第一位之前&#xff0c;必须先接收到整个分组&#xff0c;这种机制称为&#xff1a;存储转发机制 异构网络互连 用…

DC系列 DC:4

DC:4 靶机 文章目录 DC:4 靶机信息收集IP端口收集网页信息收集网站信息收集bp爆破 反弹shellnc反弹 内网信息收集收集jim用户的密码密码爆破 Charles用户密码收集 提权teehee提权 备注 信息收集 IP端口收集 用arp-scan 网段锁定ip nmap对端口服务进行详细扫描nmap -p- -sV …

C++笔记之lambda捕获列表中的‘this‘指针

C笔记之lambda捕获列表中的’this’指针 code review! 捕获this指针的lambda表达式在C中有多种应用场景。以下是一些示例&#xff1a; 异步编程&#xff1a;当您需要在异步操作中访问类的成员变量或成员函数时&#xff0c;可以使用捕获this指针的lambda表达式。例如&#xf…

Java之SpringCloud Alibaba【七】【Spring Cloud微服务网关Gateway组件】

一、网关简介 大家都都知道在微服务架构中&#xff0c;一个系统会被拆分为很多个微服务。那么作为客户端要如何去调用这么多的微服务呢?如果没有网关的存在&#xff0c;我们只能在客户端记录每个微服务的地址&#xff0c;然后分别去用。 这样的架构&#xff0c;会存在着诸多…

SpringBoot框架使用AOP + 自定义注解实现请求日志记录

一、SpringBoot记录日志 文章目录 一、SpringBoot记录日志1.1、环境搭建1.2、配置FastJson1.3、自定义LogRecord注解1.4、定义日志实体类1.5、创建HttpRequestUtil工具类1.6、定义AOP切面1.7、编写测试类1.8、运行测试 1.1、环境搭建 搭建SpringBoot工程。引入【spring-boot-st…

K8S的pod创建过程

创建流程图 用户发起请求创建deployment&#xff1b;apiserver收到创建资源的请求&#xff0c;apiserver对客户端操作进行身份认证&#xff0c;认证完成后接受该请求&#xff0c;并把相关的信息保存到etcd中&#xff0c;然后返回确认信息给客户端&#xff1b;apiserver向etcd…

【JVM】双亲委派机制、打破双亲委派机制

&#x1f40c;个人主页&#xff1a; &#x1f40c; 叶落闲庭 &#x1f4a8;我的专栏&#xff1a;&#x1f4a8; c语言 数据结构 javaEE 操作系统 Redis 石可破也&#xff0c;而不可夺坚&#xff1b;丹可磨也&#xff0c;而不可夺赤。 JVM 一、双亲委派机制1.1 双亲委派的作用1.…

Excel文档名称批量翻译的高效方法

在处理大量文件时&#xff0c;我们常常需要借助一些工具来提高工作效率。例如&#xff0c;在需要对Excel文档名称进行批量翻译时&#xff0c;一个方便快捷的工具可以帮助我们省去很多麻烦。今天&#xff0c;我将介绍一款名为固乔文件管家的软件&#xff0c;它能够帮助我们轻松实…

基于java+springboot+vue在线选课系统

项目介绍 本系统结合计算机系统的结构、概念、模型、原理、方法&#xff0c;在计算机各种优势的情况下&#xff0c;采用JAVA语言&#xff0c;结合SpringBoot框架与Vue框架以及MYSQL数据库设计并实现的。员工管理系统主要包括个人中心、课程管理、专业管理、院系信息管理、学生…

TrafficWatch 数据包嗅探器工具

TrafficWatch 是一种数据包嗅探器工具&#xff0c;允许您监视和分析 PCAP 文件中的网络流量。它提供了对各种网络协议的深入了解&#xff0c;并可以帮助进行网络故障排除、安全分析等。 针对 ARP、ICMP、TCP、UDP、DNS、DHCP、HTTP、SNMP、LLMNR 和 NetBIOS 的特定于协议的数据…

【Unity实战】最全面的库存系统(五)

文章目录 先来看看最终效果前言配置商店系统数据创建另一个NPC绘制商店UI控制商店开关列出商品添加和删除物品功能添加商品到购物车购买商品购物车删除物品商店预览效果购买和出售切换出售功能保存商店数据快捷栏物品切换和使用完结 先来看看最终效果 前言 本期也是最好一期&a…

直播间讨论区需要WebSocket,简单了解下

由于 http 存在一个明显的弊端&#xff08;消息只能有客户端推送到服务器端&#xff0c;而服务器端不能主动推送到客户端&#xff09;&#xff0c;导致如果服务器如果有连续的变化&#xff0c;这时只能使用轮询&#xff0c;而轮询效率过低&#xff0c;并不适合。于是 WebSocket…

Git 案例(企业如何使用git开发项目)

一、企业中我们是如何开发 1) 入职第一天,管理人员分配/git账号密码 2) 开发人员下载代码即文档/ 根据文档将环境搭建成功 3) 团队一般会给你讲讲项目相关的支持 4) 你接到第一个需求(或者某个功能,一般要经过沟通,分析,设计...等过程) 5) 创建feature分支(一般一个需求对应…

FPGA高端项目:图像采集+GTP+UDP架构,高速接口以太网视频传输,提供2套工程源码加QT上位机源码和技术支持

目录 1、前言免责声明本项目特点 2、相关方案推荐我这里已有的 GT 高速接口解决方案我这里已有的以太网方案 3、设计思路框架设计框图视频源选择OV5640摄像头配置及采集动态彩条视频数据组包GTP 全网最细解读GTP 基本结构GTP 发送和接收处理流程GTP 的参考时钟GTP 发送接口GTP …

【PyQt学习篇 · ⑪】:QPushButton和QCommandLinkButton的使用

文章目录 构造函数菜单设置扁平化默认处理右键菜单QCommandLinkButton的使用 构造函数 QPushButton的构造函数如下&#xff1a; """QPushButton(parent: Optional[QWidget] None)QPushButton(text: Optional[str], parent: Optional[QWidget] None)QPushButt…

自定义的卷积神经网络模型CNN,对图片进行分类并使用图片进行测试模型-适合入门,从模型到训练再到测试,开源项目

自定义的卷积神经网络模型CNN&#xff0c;对图片进行分类并使用图片进行测试模型-适合入门&#xff0c;从模型到训练再到测试&#xff1a;开源项目 开源项目完整代码及基础教程&#xff1a; https://mbd.pub/o/bread/ZZWclp5x CNN模型&#xff1a; 1.导入必要的库和模块&…

进阶C语言-指针的进阶(三)

模拟实现qsort函数 &#x1f388;1.测试bubble_sort&#xff0c;排序整型数组&#x1f388;2测试bubble_sort&#xff0c;排序结构体数组 &#x1f4dd;关于qsort函数&#xff0c;我们可以先去cpluplus网站上面了解一下&#xff1a; //1.排序整型数组&#xff0c;两个整型可以…

玻色量子“天工量子大脑”亮相中关村论坛,大放异彩

2023年5月25日至30日&#xff0c;2023中关村论坛&#xff08;科博会&#xff09;在北京盛大召开。中关村论坛&#xff08;科博会&#xff09;是面向全球科技创新交流合作的国家级平台行业盛会&#xff0c;由科技部、国家发展改革委、工业和信息化部、国务院国资委、中国科学院、…