此版本仍在开发中,尚未被视为稳定版本。对于最新的稳定版本,请使用 Spring Security 6.3.3spring-doc.cn

此版本仍在开发中,尚未被视为稳定版本。对于最新的稳定版本,请使用 Spring Security 6.3.3spring-doc.cn

如果您已经为 Reactive 应用程序执行了初始迁移步骤,那么现在可以执行特定于 Reactive 应用程序的步骤了。spring-doc.cn

Exploit Protection 迁移

以下步骤与有关如何配置 CSRF 的更改有关。spring-doc.cn

配置tokenFromMultipartDataEnabled

在 Spring Security 5.8 中,该方法已被弃用,取而代之的是 .tokenFromMultipartDataEnabledServerCsrfTokenRequestAttributeHandler#setTokenFromMultipartDataEnabledspring-doc.cn

要解决弃用问题,请使用以下代码:spring-doc.cn

使用 DSL 进行配置tokenFromMultipartDataEnabled
@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
		}
	}
}

可以替换为:spring-doc.cn

配置tokenFromMultipartDataEnabledServerCsrfTokenRequestAttributeHandler
@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 对 BREACH 保护的默认支持:CsrfTokenspring-doc.cn

CsrfTokenBREACH 保护
@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 保护给您带来麻烦,请查看以下场景以实现最佳选择退出行为:spring-doc.cn

我正在使用 AngularJS 或其他 Javascript 框架

如果同时使用 AngularJS 和 HttpClientXsrfModule(或其他框架中的类似模块),则可能会发现自动支持不再有效。CookieServerCsrfTokenRepository.withHttpOnlyFalse()spring-doc.cn

在这种情况下,你可以配置 Spring Security 来验证 cookie 中的原始数据,同时使用带有委托的自定义来保持响应的 CSRF BREACH 保护,如下所示:CsrfTokenServerCsrfTokenRequestHandlerspring-doc.cn

配置 BREACH Protection 以验证原始令牌CsrfToken
@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 保护由于其他原因对您不起作用,您可以使用以下配置选择退出:spring-doc.cn

选择退出 BREACH 保护CsrfToken
@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

如果您在进行这些更改时遇到问题,可以按照本节末尾的选择退出步骤进行操作。spring-doc.cn

在 Spring Security 5.8 中,已添加到 @EnableReactiveMethodSecurity 中,以允许应用程序选择加入 的功能。useAuthorizationManagerAuthorizationManagerspring-doc.cn

更改为useAuthorizationManagertrue

要选择加入,请更改为 LIKE:useAuthorizationManagertruespring-doc.cn

@EnableReactiveMethodSecurity
@EnableReactiveMethodSecurity

更改为:spring-doc.cn

@EnableReactiveMethodSecurity(useAuthorizationManager = true)
@EnableReactiveMethodSecurity(useAuthorizationManager = true)

检查 sAnnotationConfigurationException

useAuthorizationManager激活 Spring Security 的不可重复或其他不兼容 Comments 的更严格执行。 如果在开启后您在日志中看到 s,请按照异常消息中的说明清理应用程序的方法安全注释使用情况。useAuthorizationManagerAnnotationConfigurationExceptionspring-doc.cn

选择退出步骤

如果你遇到了响应式方法安全性的问题,你可以通过更改来选择退出:AuthorizationManagerspring-doc.cn

@EnableReactiveMethodSecurity
@EnableReactiveMethodSecurity
@EnableReactiveMethodSecurity(useAuthorizationManager = false)
@EnableReactiveMethodSecurity(useAuthorizationManager = false)

传播 sAuthenticationServiceException

AuthenticationFilterAuthenticationServiceException传播到ServerAuthenticationEntryPoint。 由于 s 表示服务器端错误而不是客户端错误,因此在 6.0 中,这会更改以将它们传播到容器。AuthenticationServiceExceptionspring-doc.cn

配置为重新抛出ServerAuthenticationFailureHandlerAuthenticationServiceException

要为 6.0 默认值做准备,并且应该配置为 rethrow s。httpBasicoauth2ResourceServerAuthenticationServiceExceptionspring-doc.cn

对于每个 API,为 和 为 构建适当的身份验证入口点 :httpBasicoauth2ResourceServerspring-doc.cn

ServerAuthenticationEntryPoint bearerEntryPoint = new BearerTokenServerAuthenticationEntryPoint();
ServerAuthenticationEntryPoint basicEntryPoint = new HttpStatusServerEntryPoint(HttpStatus.UNAUTHORIZED);
val bearerEntryPoint: ServerAuthenticationEntryPoint = BearerTokenServerAuthenticationEntryPoint()
val basicEntryPoint: ServerAuthenticationEntryPoint = HttpStatusServerEntryPoint(HttpStatus.UNAUTHORIZED)

如果您将 custom 用于其中一个或两个机制,请改用该 custom 来执行其余步骤。AuthenticationEntryPointspring-doc.cn

然后,为每个 API 构造并配置 a:ServerAuthenticationEntryPointFailureHandlerspring-doc.cn

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 中,如下所示:spring-doc.cn

http
    .httpBasic((basic) -> basic.authenticationFailureHandler(basicFailureHandler))
    .oauth2ResourceServer((oauth2) -> oauth2.authenticationFailureHandler(bearerFailureHandler))
http {
    httpBasic {
        authenticationFailureHandler = basicFailureHandler
    }
    oauth2ResourceServer {
        authenticationFailureHandler = bearerFailureHandler
    }
}

选择退出步骤

要选择退出 6.0 默认值并继续传递给 s,您可以按照与上述相同的步骤操作,但设置为 false。AuthenticationServiceExceptionServerAuthenticationEntryPointrethrowAuthenticationServiceExceptionspring-doc.cn

如果您将 custom 用于其中一个或两个机制,请改用该 custom 来执行其余步骤。AuthenticationEntryPointspring-doc.cn

添加注释@Configuration

在 6.0 中,已从 和 中删除。@Configuration@EnableWebFluxSecurity@EnableReactiveMethodSecurityspring-doc.cn

为此,无论您在何处使用这些注释之一,都可能需要添加 . 例如,从以下位置更改:@Configuration@EnableReactiveMethodSecurityspring-doc.cn

@EnableReactiveMethodSecurity
public class MyConfiguration {
	// ...
}
@EnableReactiveMethodSecurity
open class MyConfiguration {
	// ...
}
@Configuration
@EnableReactiveMethodSecurity
public class MyConfiguration {
	// ...
}
@Configuration
@EnableReactiveMethodSecurity
open class MyConfiguration {
	// ...
}

解决 OAuth2 客户端弃用问题

ServerOAuth2AuthorizedClientExchangeFilterFunction

该方法可替换为以下之一:setAccessTokenExpiresSkew(…​)spring-doc.cn

  • ClientCredentialsReactiveOAuth2AuthorizedClientProvider#setClockSkew(…​)spring-doc.cn

  • RefreshTokenReactiveOAuth2AuthorizedClientProvider#setClockSkew(…​)spring-doc.cn

  • JwtBearerReactiveOAuth2AuthorizedClientProvider#setClockSkew(…​)spring-doc.cn

该方法可以替换为 constructor 。setClientCredentialsTokenResponseClient(…​)ServerOAuth2AuthorizedClientExchangeFilterFunction(ReactiveOAuth2AuthorizedClientManager)spring-doc.cn

有关更多信息,请参阅 客户端凭证spring-doc.cn

WebSessionOAuth2ServerAuthorizationRequestRepository

该方法没有直接的替代。setAllowMultipleAuthorizationRequests(…​)spring-doc.cn

UnAuthenticatedServerOAuth2AuthorizedClientRepository

该类没有直接替换。该类的用法可以替换为 。UnAuthenticatedServerOAuth2AuthorizedClientRepositoryAuthorizedClientServiceReactiveOAuth2AuthorizedClientManagerspring-doc.cn

有关更多信息,请参阅 客户端凭证spring-doc.cn

添加到注释@Configuration@Enable*

在 6.0 中,所有 Spring Security 的 Comments 都已删除。 虽然方便,但它与其他 Spring 项目不一致,尤其是 Spring Framework 的注释。 此外,在 Spring Framework 中引入对的支持提供了另一个原因,可以从 Spring Security 的注释中删除元注释,并允许用户选择进入他们喜欢的配置模式。@Enable*@Configuration@Enable*@Configuration(proxyBeanMethods=false)@Configuration@Enable*spring-doc.cn

以下注释已删除:@Configurationspring-doc.cn

例如,如果您使用的是 ,则需要更改:@EnableWebFluxSecurityspring-doc.cn

@EnableWebFluxSecurity
public class SecurityConfig {
	// ...
}
@Configuration
@EnableWebFluxSecurity
public class SecurityConfig {
	// ...
}

这同样适用于上面列出的所有其他 Comments。spring-doc.cn