对于最新的稳定版本,请使用 Spring Security 6.3.1! |
对于最新的稳定版本,请使用 Spring Security 6.3.1! |
如果您已经执行了 Reactive 应用程序的初始迁移步骤,那么您现在就可以执行特定于 Reactive 应用程序的步骤了。
漏洞利用保护迁移
以下步骤与有关如何配置 CSRF 的更改相关。
配置tokenFromMultipartDataEnabled
在 Spring Security 5.8 中,该方法已被弃用,取而代之的是 .tokenFromMultipartDataEnabled
ServerCsrfTokenRequestAttributeHandler#setTokenFromMultipartDataEnabled
若要解决弃用问题,请执行以下代码:
tokenFromMultipartDataEnabled
-
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 违规
您可以使用以下配置选择加入 Spring Security 6 对 BREACH 保护的默认支持:CsrfToken
CsrfToken
漏洞保护-
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()
在这种情况下,您可以配置Spring Security以验证cookie中的原始数据,同时使用具有委派的自定义自定义来保持CSRF BREACH 对响应的保护,如下所示:CsrfToken
ServerCsrfTokenRequestHandler
CsrfToken
-
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
-
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
通过 AuthorizationManager
API 和直接使用 Spring AOP 改进了方法安全性。
如果您在进行这些更改时遇到问题,可以按照本节末尾的选择退出步骤进行操作。
在 Spring Security 5.8 中,已添加到@EnableReactiveMethodSecurity
,以允许应用程序选择加入 的功能。useAuthorizationManager
AuthorizationManager
更改为useAuthorizationManager
true
要选择加入,请更改为如下所示:useAuthorizationManager
true
-
Java
-
Kotlin
@EnableReactiveMethodSecurity
@EnableReactiveMethodSecurity
更改为:
-
Java
-
Kotlin
@EnableReactiveMethodSecurity(useAuthorizationManager = true)
@EnableReactiveMethodSecurity(useAuthorizationManager = true)
传播 sAuthenticationServiceException
AuthenticationFilter
将 AuthenticationServiceException
传播到 ServerAuthenticationEntryPoint
。
由于 s 表示服务器端错误而不是客户端错误,因此在 6.0 中,此更改为将它们传播到容器。AuthenticationServiceException
配置为重新抛出ServerAuthenticationFailureHandler
AuthenticationServiceException
为 6.0 默认值做准备,并应配置为重新抛出 s。httpBasic
oauth2ResourceServer
AuthenticationServiceException
对于每个,为 和 构造适当的身份验证入口点: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
为此,无论您在哪里使用这些注释之一,您可能需要添加 .
例如,更改为:@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 的所有注解都被删除了。
虽然方便,但它与其他 Spring 项目不一致,尤其是 Spring Framework 的注解。
此外,在 Spring Framework 中引入对 的支持提供了另一个原因,可以从 Spring Security 的注解中删除元注解,并允许用户选择他们喜欢的配置模式。@Enable*
@Configuration
@Enable*
@Configuration(proxyBeanMethods=false)
@Configuration
@Enable*
删除了以下注释:@Configuration
-
@EnableGlobalAuthentication
-
@EnableGlobalMethodSecurity
-
@EnableMethodSecurity
-
@EnableReactiveMethodSecurity
-
@EnableWebSecurity
-
@EnableWebFluxSecurity
例如,如果您正在使用 ,则需要更改:@EnableWebFluxSecurity
-
Java
@EnableWebFluxSecurity
public class SecurityConfig {
// ...
}
自:
-
Java
@Configuration
@EnableWebFluxSecurity
public class SecurityConfig {
// ...
}
这同样适用于上面列出的所有其他注释。