此版本仍在开发中,尚未被视为稳定版本。对于最新的稳定版本,请使用 Spring Security 6.4.3! |
反应式迁移
如果您已经为 Reactive 应用程序执行了初始迁移步骤,那么现在可以执行特定于 Reactive 应用程序的步骤了。
Exploit Protection 迁移
以下步骤与有关如何配置 CSRF 的更改有关。
配置tokenFromMultipartDataEnabled
在 Spring Security 5.8 中,该方法tokenFromMultipartDataEnabled
已弃用,取而代之的是ServerCsrfTokenRequestAttributeHandler#setTokenFromMultipartDataEnabled
.
要解决弃用问题,请使用以下代码:
tokenFromMultipartDataEnabled
使用 DSL-
Java
-
Kotlin
@Bean
SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http) {
http
// ...
.csrf((csrf) -> csrf
.tokenFromMultipartDataEnabled(true)
);
return http.build();
}
@Bean
open fun securityWebFilterChain(http: ServerHttpSecurity): SecurityWebFilterChain {
return http {
// ...
csrf {
tokenFromMultipartDataEnabled = true
}
}
}
可以替换为:
tokenFromMultipartDataEnabled
跟ServerCsrfTokenRequestAttributeHandler
-
Java
-
Kotlin
@Bean
SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http) {
ServerCsrfTokenRequestAttributeHandler requestHandler = new ServerCsrfTokenRequestAttributeHandler();
requestHandler.setTokenFromMultipartDataEnabled(true);
http
// ...
.csrf((csrf) -> csrf
.csrfTokenRequestHandler(requestHandler)
);
return http.build();
}
@Bean
open fun securityWebFilterChain(http: ServerHttpSecurity): SecurityWebFilterChain {
val requestHandler = ServerCsrfTokenRequestAttributeHandler()
requestHandler.tokenFromMultipartDataEnabled = true
return http {
// ...
csrf {
csrfTokenRequestHandler = requestHandler
}
}
}
防止 CSRF BREACH
您可以选择 Spring Security 6 对CsrfToken
使用以下配置:
CsrfToken
BREACH 保护-
Java
-
Kotlin
@Bean
SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http) {
XorServerCsrfTokenRequestAttributeHandler requestHandler = new XorServerCsrfTokenRequestAttributeHandler();
// ...
http
// ...
.csrf((csrf) -> csrf
.csrfTokenRequestHandler(requestHandler)
);
return http.build();
}
@Bean
open fun securityWebFilterChain(http: ServerHttpSecurity): SecurityWebFilterChain {
val requestHandler = XorServerCsrfTokenRequestAttributeHandler()
// ...
return http {
// ...
csrf {
csrfTokenRequestHandler = requestHandler
}
}
}
选择退出步骤
如果配置 CSRF BREACH 保护给您带来麻烦,请查看以下场景以实现最佳选择退出行为:
我正在使用 AngularJS 或其他 Javascript 框架
如果你正在使用 AngularJS 和 HttpClientXsrfModule(或其他框架中的类似模块)以及CookieServerCsrfTokenRepository.withHttpOnlyFalse()
,您可能会发现 Automatic Support 不再有效。
在这种情况下,您可以配置 Spring Security 来验证原始CsrfToken
从 cookie 中,同时使用自定义ServerCsrfTokenRequestHandler
使用委派,如下所示:
CsrfToken
用于验证原始令牌的 BREACH Protection-
Java
-
Kotlin
@Bean
SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http) {
CookieServerCsrfTokenRepository tokenRepository = CookieServerCsrfTokenRepository.withHttpOnlyFalse();
XorServerCsrfTokenRequestAttributeHandler delegate = new XorServerCsrfTokenRequestAttributeHandler();
// Use only the handle() method of XorServerCsrfTokenRequestAttributeHandler and the
// default implementation of resolveCsrfTokenValue() from ServerCsrfTokenRequestHandler
ServerCsrfTokenRequestHandler requestHandler = delegate::handle;
http
// ...
.csrf((csrf) -> csrf
.csrfTokenRepository(tokenRepository)
.csrfTokenRequestHandler(requestHandler)
);
return http.build();
}
@Bean
WebFilter csrfCookieWebFilter() {
return (exchange, chain) -> {
Mono<CsrfToken> csrfToken = exchange.getAttributeOrDefault(CsrfToken.class.getName(), Mono.empty());
return csrfToken.doOnSuccess(token -> {
/* Ensures the token is subscribed to. */
}).then(chain.filter(exchange));
};
}
@Bean
open fun securityWebFilterChain(http: ServerHttpSecurity): SecurityWebFilterChain {
val tokenRepository = CookieServerCsrfTokenRepository.withHttpOnlyFalse()
val delegate = XorServerCsrfTokenRequestAttributeHandler()
// Use only the handle() method of XorServerCsrfTokenRequestAttributeHandler and the
// default implementation of resolveCsrfTokenValue() from ServerCsrfTokenRequestHandler
val requestHandler = ServerCsrfTokenRequestHandler(delegate::handle)
return http.invoke {
// ...
csrf {
csrfTokenRepository = tokenRepository
csrfTokenRequestHandler = requestHandler
}
}
}
@Bean
fun csrfCookieWebFilter(): WebFilter {
return WebFilter { exchange, chain ->
val csrfToken = exchange.getAttribute<Mono<CsrfToken>>(CsrfToken::class.java.name) ?: Mono.empty()
csrfToken.doOnSuccess {
/* Ensures the token is subscribed to. */
}.then(chain.filter(exchange))
}
}
出于另一个原因,我需要选择退出 CSRF BREACH 保护
如果 CSRF BREACH 保护由于其他原因对您不起作用,您可以使用以下配置选择退出:
CsrfToken
BREACH 保护-
Java
-
Kotlin
@Bean
SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http) {
ServerCsrfTokenRequestAttributeHandler requestHandler = new ServerCsrfTokenRequestAttributeHandler();
http
// ...
.csrf((csrf) -> csrf
.csrfTokenRequestHandler(requestHandler)
);
return http.build();
}
@Bean
open fun securityWebFilterChain(http: ServerHttpSecurity): SecurityWebFilterChain {
val requestHandler = ServerCsrfTokenRequestAttributeHandler()
return http {
// ...
csrf {
csrfTokenRequestHandler = requestHandler
}
}
}
用AuthorizationManager
针对 Method Security
方法安全性已通过以下方式得到改进这AuthorizationManager
应用程序接口以及直接使用 Spring AOP。
如果您在进行这些更改时遇到问题,可以按照本节末尾的选择退出步骤进行作。
在 Spring Security 5.8 中,useAuthorizationManager
已添加到@EnableReactiveMethodSecurity
允许应用程序选择加入AuthorizationManager
的功能。
改变useAuthorizationManager
自true
要选择加入,请将useAuthorizationManager
自true
这样:
-
Java
-
Kotlin
@EnableReactiveMethodSecurity
@EnableReactiveMethodSecurity
更改为:
-
Java
-
Kotlin
@EnableReactiveMethodSecurity(useAuthorizationManager = true)
@EnableReactiveMethodSecurity(useAuthorizationManager = true)
传播AuthenticationServiceException
s
AuthenticationFilter
传播AuthenticationServiceException
s 到ServerAuthenticationEntryPoint
.
因为AuthenticationServiceException
表示服务器端错误而不是客户端错误,在 6.0 中,此更改会将它们传播到容器。
配置ServerAuthenticationFailureHandler
重新抛出AuthenticationServiceException
s
要为 6.0 默认值做准备,httpBasic
和oauth2ResourceServer
应配置为 rethrowAuthenticationServiceException
s.
对于每个 API,为httpBasic
和oauth2ResourceServer
:
-
Java
-
Kotlin
ServerAuthenticationEntryPoint bearerEntryPoint = new BearerTokenServerAuthenticationEntryPoint();
ServerAuthenticationEntryPoint basicEntryPoint = new HttpStatusServerEntryPoint(HttpStatus.UNAUTHORIZED);
val bearerEntryPoint: ServerAuthenticationEntryPoint = BearerTokenServerAuthenticationEntryPoint()
val basicEntryPoint: ServerAuthenticationEntryPoint = HttpStatusServerEntryPoint(HttpStatus.UNAUTHORIZED)
如果您使用自定义 |
然后,构造并配置一个ServerAuthenticationEntryPointFailureHandler
对于每个:
-
Java
-
Kotlin
AuthenticationFailureHandler bearerFailureHandler = new ServerAuthenticationEntryPointFailureHandler(bearerEntryPoint);
bearerFailureHandler.setRethrowAuthenticationServiceException(true);
AuthenticationFailureHandler basicFailureHandler = new ServerAuthenticationEntryPointFailureHandler(basicEntryPoint);
basicFailureHandler.setRethrowAuthenticationServiceException(true)
val bearerFailureHandler: AuthenticationFailureHandler = ServerAuthenticationEntryPointFailureHandler(bearerEntryPoint)
bearerFailureHandler.setRethrowAuthenticationServiceException(true)
val basicFailureHandler: AuthenticationFailureHandler = ServerAuthenticationEntryPointFailureHandler(basicEntryPoint)
basicFailureHandler.setRethrowAuthenticationServiceException(true)
最后,将每个身份验证失败处理程序连接到 DSL 中,如下所示:
-
Java
-
Kotlin
http
.httpBasic((basic) -> basic.authenticationFailureHandler(basicFailureHandler))
.oauth2ResourceServer((oauth2) -> oauth2.authenticationFailureHandler(bearerFailureHandler))
http {
httpBasic {
authenticationFailureHandler = basicFailureHandler
}
oauth2ResourceServer {
authenticationFailureHandler = bearerFailureHandler
}
}
加@Configuration
注解
在 6.0 中,@Configuration
已从@EnableWebFluxSecurity
和@EnableReactiveMethodSecurity
.
为此,无论您在何处使用这些 annotation 之一,都可能需要添加@Configuration
.
例如@EnableReactiveMethodSecurity
更改:
-
Java
@EnableReactiveMethodSecurity
public class MyConfiguration {
// ...
}
-
Kotlin
@EnableReactiveMethodSecurity
open class MyConfiguration {
// ...
}
自:
-
Java
@Configuration
@EnableReactiveMethodSecurity
public class MyConfiguration {
// ...
}
-
Kotlin
@Configuration
@EnableReactiveMethodSecurity
open class MyConfiguration {
// ...
}
解决 OAuth2 客户端弃用问题
ServerOAuth2AuthorizedClientExchangeFilterFunction
方法setAccessTokenExpiresSkew(…)
可以替换为以下之一:
-
ClientCredentialsReactiveOAuth2AuthorizedClientProvider#setClockSkew(…)
-
RefreshTokenReactiveOAuth2AuthorizedClientProvider#setClockSkew(…)
-
JwtBearerReactiveOAuth2AuthorizedClientProvider#setClockSkew(…)
方法setClientCredentialsTokenResponseClient(…)
可以替换为构造函数ServerOAuth2AuthorizedClientExchangeFilterFunction(ReactiveOAuth2AuthorizedClientManager)
.
有关更多信息,请参阅 客户端凭证 。 |
加@Configuration
自@Enable*
附注
在 6.0 中,所有 Spring Security 的@Enable*
注释具有@Configuration
删除。
虽然方便,但它与其他 Spring 项目不一致,尤其是 Spring Framework 的@Enable*
附注。
此外,引入了对@Configuration(proxyBeanMethods=false)
提供了另一个将@Configuration
来自 Spring Security 的 meta-annotation@Enable*
注释,并允许用户选择加入他们的首选配置模式。
以下注释具有@Configuration
删除:
-
@EnableGlobalAuthentication
-
@EnableGlobalMethodSecurity
-
@EnableMethodSecurity
-
@EnableReactiveMethodSecurity
-
@EnableWebSecurity
-
@EnableWebFluxSecurity
例如,如果您正在使用@EnableWebFluxSecurity
,您将需要更改:
-
Java
@EnableWebFluxSecurity
public class SecurityConfig {
// ...
}
自:
-
Java
@Configuration
@EnableWebFluxSecurity
public class SecurityConfig {
// ...
}
这同样适用于上面列出的所有其他 Comments。