Spring Security 6.4 新特性
Spring Security 6.4 提供了许多新特性。以下是该版本的主要亮点,您也可以查看版本说明以获取每个特性和错误修复的详细列表。
弃用通知
随着我们接近 Spring Security 7,及时了解弃用情况非常重要。因此,本节指出了 6.4 版本中的弃用项。
-
方法安全 (Method Security) - 建议使用
AuthorizationManager#authorize
代替AuthorizationManager#check
,后者已被弃用。这主要是为了让返回类型成为接口而不是具体类。如果您正在调用AuthorizationManager#check
,请改为调用AuthorizationManager#authorize
。与此相关,接受
AuthorizationDecision
参数的AuthorizationEventPublisher#publishEvent
方法已被弃用,建议使用接受AuthorizationResult
接口参数的同名方法。 -
方法安全 (Method Security) -
PrePostTemplateDefaults
已被弃用,建议使用更通用的AnnotationTemplateExpressionDefaults
,因为现在 `@AuthenticationPrincipal` 和 `@CurrentSecurityContext` 也支持元注解属性。如果您正在构造PrePostTemplateDefaults
,请将其更改为AnnotationTemplateExpressionDefaults
。 -
OAuth 2.0 -
NimbusOpaqueTokenIntrospector
已被弃用,建议使用SpringOpaqueTokenIntrospector
,以移除 Spring Security OAuth 2.0 资源服务器对oidc-oauth2-sdk
包的依赖。如果您正在构造NimbusOpaqueTokenIntrospector
,请将其替换为SpringOpaqueTokenIntrospector
的构造函数。 -
OAuth 2.0 -
DefaultAuthorizationCodeTokenResponseClient
、DefaultClientCredentialsTokenResponseClient
、DefaultJwtBearerTokenResponseClient
、DefaultPasswordTokenResponseClient
、DefaultRefreshTokenTokenResponseClient
和DefaultTokenExchangeTokenResponseClient
已被弃用,建议使用其RestClient
等效实现。与此相关,
JwtBearerGrantRequestEntityConverter
、OAuth2AuthorizationCodeGrantRequestEntityConverter
、OAuth2ClientCredentialsGrantRequestEntityConverter
、OAuth2PasswordGrantRequestEntityConverter
、OAuth2RefreshTokenGrantRequestEntityConverter
已被弃用,建议改为向上述令牌响应客户端之一提供DefaultOAuth2TokenRequestParametersConverter
的实例。例如,如果您有以下配置
private static class MyCustomConverter extends AbstractOAuth2AuthorizationGrantRequestEntityConverter<OAuth2AuthorizationCodeGrantRequest> { @Override protected MultiValueMap<String, String> createParameters (OAuth2AuthorizationCodeGrantRequest request) { MultiValueMap<String, String> parameters = super.createParameters(request); parameters.add("custom", "value"); return parameters; } } @Bean OAuth2AccessTokenResponseClient authorizationCode() { DefaultAuthorizationCodeTokenResponseClient client = new DefaultAuthorizationCodeTokenResponseClient(); Converter<AuthorizationCodeGrantRequest, RequestEntity<?>> entityConverter = new OAuth2AuthorizationCodeGrantRequestEntityConverter(); entityConverter.setParametersConverter(new MyCustomConverter()); client.setRequestEntityConverter(entityConverter); return client; }
此配置已弃用,因为它使用了
DefaultAuthorizationCodeTokenResponseClient
和OAuth2AuthorizationCodeGrantRequestEntityConverter
。现在推荐的配置是private static class MyCustomConverter implements Converter<OAuth2AuthorizationCodeGrantRequest, Map<String, String>> { @Override public MultiValueMap<String, String> convert(OAuth2AuthorizeCodeGrantRequest request) { MultiValueMap<String, String> parameters = OAuth2AuthorizationCodeGrantRequest.defaultParameters(request); parameters.add("custom", "value"); return parameters; } } @Bean OAuth2AccessTokenResponseClient authorizationCode() { RestClientAuthorizationCodeTokenResponseClient client = new RestClientAuthorizationCodeTokenResponseClient(); client.setParametersConverter(new MyCustomConverter()); return client; }
-
SAML 2.0 - Spring Security SAML 2.0 服务提供者接口的未版本化 OpenSAML 实现已被弃用,建议使用版本化实现。例如,
OpenSamlAuthenticationTokenConverter
现在已被OpenSaml4AuthenticationTokenConverter
和OpenSaml5AuthenticationTokenConverter
替代。如果您正在构造这些已弃用版本之一,请将其替换为您正在使用的 OpenSAML 版本对应的实现。 -
SAML 2.0 - 关于
AssertingPartyDetails
的方法已被弃用,建议使用接受AssertingPartyMetadata
接口参数的等效方法。 -
LDAP -
DistinguishedName
的用法现已弃用,以与 Spring LDAP 的弃用保持一致。
通行密钥
Spring Security 现在支持通行密钥。
方法安全
-
所有方法安全注解现在都支持 Spring Framework 的 `@AliasFor`。
-
`@AuthenticationPrincipal` 和 `@CurrentSecurityContext` 现在支持注解模板。
这意味着您现在可以像这样使用 Spring 的元注解支持
-
Java
-
Kotlin
@Target(TargetType.TYPE) @Retention(RetentionPolicy.RUNTIME) @AuthenticationPrincipal("claims['{claim}']") @interface CurrentUsername { String claim() default "sub"; } // ... @GetMapping public String method(@CurrentUsername("username") String username) { // ... }
annotation CurrentUsername(val claim: String = "sub") // ... @GetMapping fun method(@CurrentUsername("username") val username: String): String { // ... }
-
-
对齐 Security 注解搜索与
AbstractFallbackMethodSecurityMetadataSource
的算法进行了一些改进。这有助于从早期版本的 Spring Security 进行迁移。 -
Native 应用现在可以使用 `@AuthorizeReturnObject`。
-
Native 应用现在可以在 `@PreAuthorize` 和 `@PostAuthorize` 中引用 bean。
-
SecurityAnnotationScanners
提供了一个方便的 API,用于扫描 Security 注解以及将 Security 的选择和模板特性添加到自定义注解中。
OAuth 2.0
-
oauth2Login()
现在接受将OAuth2AuthorizationRequestResolver
作为 `@Bean`。 -
ClientRegistrations
现在支持外部获取的配置。 -
在响应式
oauth2Login()
中向 DSL 添加了loginPage()
。 -
OIDC Back-Channel 支持现在接受类型为
logout+jwt
的退出登录令牌。 -
RestClient
现在可以配置OAuth2ClientHttpRequestInterceptor
来访问受保护的资源请求。 -
添加了基于
RestClient
的OAuth2AccessTokenResponseClient
实现,以便更一致地配置访问令牌请求。要启用
RestClient
支持,只需为每种授权类型发布一个 bean,如下例所示-
Java
-
Kotlin
@Configuration public class SecurityConfig { @Bean public OAuth2AccessTokenResponseClient<OAuth2AuthorizationCodeGrantRequest> authorizationCodeAccessTokenResponseClient() { return new RestClientAuthorizationCodeTokenResponseClient(); } @Bean public OAuth2AccessTokenResponseClient<OAuth2RefreshTokenGrantRequest> refreshTokenAccessTokenResponseClient() { return new RestClientRefreshTokenTokenResponseClient(); } @Bean public OAuth2AccessTokenResponseClient<OAuth2ClientCredentialsGrantRequest> clientCredentialsAccessTokenResponseClient() { return new RestClientClientCredentialsTokenResponseClient(); } @Bean public OAuth2AccessTokenResponseClient<JwtBearerGrantRequest> jwtBearerAccessTokenResponseClient() { return new RestClientJwtBearerTokenResponseClient(); } @Bean public OAuth2AccessTokenResponseClient<TokenExchangeGrantRequest> tokenExchangeAccessTokenResponseClient() { return new RestClientTokenExchangeTokenResponseClient(); } }
@Configuration class SecurityConfig { @Bean fun authorizationCodeAccessTokenResponseClient(): OAuth2AccessTokenResponseClient<OAuth2AuthorizationCodeGrantRequest> { return RestClientAuthorizationCodeTokenResponseClient() } @Bean fun refreshTokenAccessTokenResponseClient(): OAuth2AccessTokenResponseClient<OAuth2RefreshTokenGrantRequest> { return RestClientRefreshTokenTokenResponseClient() } @Bean fun clientCredentialsAccessTokenResponseClient(): OAuth2AccessTokenResponseClient<OAuth2ClientCredentialsGrantRequest> { return RestClientClientCredentialsTokenResponseClient() } @Bean fun jwtBearerAccessTokenResponseClient(): OAuth2AccessTokenResponseClient<JwtBearerGrantRequest> { return RestClientJwtBearerTokenResponseClient() } @Bean fun tokenExchangeAccessTokenResponseClient(): OAuth2AccessTokenResponseClient<TokenExchangeGrantRequest> { return RestClientTokenExchangeTokenResponseClient() } }
-
-
令牌交换现在支持刷新令牌。
SAML 2.0
-
添加了OpenSAML 5 支持。现在您可以使用 OpenSAML 4 或 OpenSAML 5;默认情况下,Spring Security 将根据您 classpath 中存在的版本选择正确的实现。
-
简化了使用 EntityID 作为
registrationId
的过程。一种常见模式是通过其
entityID
来标识断言方。在以前的版本中,这需要直接配置OpenSamlAuthenticationRequestResolver
。现在,请求解析器除了在路径中查找registrationId
外,默认还将其作为请求参数查找。这允许您使用RelyingPartyRegistrations
或OpenSaml4/5AssertingPartyMetadataRepository
,而无需修改registrationId
值或自定义请求解析器。与此相关,您现在可以配置您的
authenticationRequestUri
包含一个查询参数。 -
现在可以根据元数据的过期时间在后台刷新断言方 (Asserting Parties)。
例如,您现在可以使用
OpenSaml5AssertingPartyMetadataRepository
来实现-
Java
-
Kotlin
@Component public class RefreshableRelyingPartyRegistrationRepository implements IterableRelyingPartyRegistrationRepository { private final AssertingPartyMetadataRepository assertingParties = OpenSaml5AssertingPartyMetadataRepository .fromTrustedMetadataLocation("https://idp.example.org").build(); @Override public RelyingPartyRegistration findByRegistrationId(String registrationId) { AssertingPartyMetadata assertingParty = this.assertingParties.findByEntityId(registrationId); return RelyingPartyRegistration.withAssertingPartyMetadata(assertingParty) // relying party configurations .build(); } // ... }
@Component open class RefreshableRelyingPartyRegistrationRepository: IterableRelyingPartyRegistrationRepository { private val assertingParties: AssertingPartyMetadataRepository = OpenSaml5AssertingPartyMetadataRepository .fromTrustedMetadataLocation("https://idp.example.org").build() override fun findByRegistrationId(String registrationId): RelyingPartyRegistration { val assertingParty = this.assertingParties.findByEntityId(registrationId) return RelyingPartyRegistration.withAssertingPartyMetadata(assertingParty) // relying party configurations .build() } // ... }
此实现还支持验证元数据的签名。
-
-
您现在可以签署依赖方元数据。
-
RelyingPartyRegistrationRepository
的结果现在可以缓存。如果您希望在应用启动后延迟加载注册值,这将非常有用。如果您希望通过 Spring Cache 控制何时刷新元数据,这也很有用。 -
为了与 SAML 2.0 标准对齐,元数据端点现在使用
application/samlmetadata+xml
MIME 类型。
Web
-
CSRF BREACH 令牌现在更加一致。
-
“记住我” cookie 现在更加可定制。
-
安全过滤器链能发现更多无效配置。例如,在 `any-request` 过滤器链之后声明的过滤器链是无效的,因为它永远不会被调用。
-
Java
-
Kotlin
@Bean @Order(0) SecurityFilterChain api(HttpSecurity http) throws Exception { http // implicit securityMatcher("/**") .authorizeHttpRequests(...) .httpBasic(...) return http.build(); } @Bean @Order(1) SecurityFilterChain app(HttpSecurity http) throws Exception { http .securityMatcher("/app/**") .authorizeHttpRequests(...) .formLogin(...) return http.build(); }
@Bean @Order(0) fun api(val http: HttpSecurity): SecurityFilterChain { http { authorizeHttpRequests { // ... } } return http.build() } @Bean @Order(1) fun app(val http: HttpSecurity): SecurityFilterChain { http { securityMatcher("/app/**") authorizeHttpRequests { // ... } } return http.build() }
您可以在相关 ticket 中阅读更多信息。
-
-
ServerHttpSecurity
现在将ServerWebExchangeFirewall
作为一个 `@Bean` 拾取。
可观测性
可观测性现在支持分别开关授权、认证和请求的可观测性。例如,要关闭过滤器链的可观测性,您可以发布一个如下所示的 `@Bean`。
-
Java
-
Kotlin
@Bean
SecurityObservationSettings allSpringSecurityObservations() {
return SecurityObservationSettings.withDefaults()
.shouldObserveFilterChains(false).build();
}
@Bean
fun allSpringSecurityObservations(): SecurityObservationSettings {
return SecurityObservationSettings.builder()
.shouldObserveFilterChains(false).build()
}
Kotlin
-
Kotlin DSL 现在支持 SAML 2.0 以及
GrantedAuthorityDefaults
和RoleHierarchy
的 `@Bean`。 -
`@PreFilter` 和 `@PostFilter` 现在在 Kotlin 中得到支持。
-
Kotlin 响应式 DSL 现在支持
SecurityContextRepository
。
ACL
-
AclAuthorizationStrategyImpl
现在支持RoleHierarchy
。