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

反应式迁移

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

Exploit Protection 迁移

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

配置tokenFromMultipartDataEnabled

在 Spring Security 5.8 中,该方法tokenFromMultipartDataEnabled已弃用,取而代之的是ServerCsrfTokenRequestAttributeHandler#setTokenFromMultipartDataEnabled.spring-doc.cadn.net.cn

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

配置tokenFromMultipartDataEnabled使用 DSL
@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.cadn.net.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 对CsrfToken使用以下配置:spring-doc.cadn.net.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.cadn.net.cn

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

如果你正在使用 AngularJS 和 HttpClientXsrfModule(或其他框架中的类似模块)以及CookieServerCsrfTokenRepository.withHttpOnlyFalse(),您可能会发现 Automatic Support 不再有效。spring-doc.cadn.net.cn

在这种情况下,您可以配置 Spring Security 来验证原始CsrfToken从 cookie 中,同时使用自定义ServerCsrfTokenRequestHandler使用委派,如下所示:spring-doc.cadn.net.cn

配置CsrfToken用于验证原始令牌的 BREACH Protection
@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.cadn.net.cn

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

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

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

改变useAuthorizationManagertrue

要选择加入,请将useAuthorizationManagertrue这样:spring-doc.cadn.net.cn

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

检查AnnotationConfigurationExceptions

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

选择退出步骤

如果您遇到麻烦AuthorizationManager为了响应式方法的安全性,你可以通过更改以下内容来选择退出:spring-doc.cadn.net.cn

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

传播AuthenticationServiceExceptions

AuthenticationFilter传播AuthenticationServiceExceptions 到ServerAuthenticationEntryPoint. 因为AuthenticationServiceException表示服务器端错误而不是客户端错误,在 6.0 中,此更改会将它们传播到容器。spring-doc.cadn.net.cn

配置ServerAuthenticationFailureHandler重新抛出AuthenticationServiceExceptions

要为 6.0 默认值做准备,httpBasicoauth2ResourceServer应配置为 rethrowAuthenticationServiceExceptions.spring-doc.cadn.net.cn

对于每个 API,为httpBasicoauth2ResourceServer:spring-doc.cadn.net.cn

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

如果您使用自定义AuthenticationEntryPoint对于其中一个或两个机制,请改用该机制来执行其余步骤。spring-doc.cadn.net.cn

然后,构造并配置一个ServerAuthenticationEntryPointFailureHandler对于每个:spring-doc.cadn.net.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.cadn.net.cn

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

选择退出步骤

选择退出 6.0 默认值,而是继续传递AuthenticationServiceExceptionon 到ServerAuthenticationEntryPoints,您可以按照上述相同的步骤进行作,但 setrethrowAuthenticationServiceException设置为 false。spring-doc.cadn.net.cn

@Configuration注解

在 6.0 中,@Configuration已从@EnableWebFluxSecurity@EnableReactiveMethodSecurity.spring-doc.cadn.net.cn

为此,无论您在何处使用这些 annotation 之一,都可能需要添加@Configuration. 例如@EnableReactiveMethodSecurity更改:spring-doc.cadn.net.cn

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

解决 OAuth2 客户端弃用问题

ServerOAuth2AuthorizedClientExchangeFilterFunction

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

方法setClientCredentialsTokenResponseClient(…​)可以替换为构造函数ServerOAuth2AuthorizedClientExchangeFilterFunction(ReactiveOAuth2AuthorizedClientManager).spring-doc.cadn.net.cn

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

WebSessionOAuth2ServerAuthorizationRequestRepository

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

UnAuthenticatedServerOAuth2AuthorizedClientRepository

UnAuthenticatedServerOAuth2AuthorizedClientRepository没有直接替代。该类的用法可以替换为AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager.spring-doc.cadn.net.cn

@Configuration@Enable*附注

在 6.0 中,所有 Spring Security 的@Enable*注释具有@Configuration删除。 虽然方便,但它与其他 Spring 项目不一致,尤其是 Spring Framework 的@Enable*附注。 此外,引入了对@Configuration(proxyBeanMethods=false)提供了另一个将@Configuration来自 Spring Security 的 meta-annotation@Enable*注释,并允许用户选择加入他们的首选配置模式。spring-doc.cadn.net.cn

以下注释具有@Configuration删除:spring-doc.cadn.net.cn

例如,如果您正在使用@EnableWebFluxSecurity,您将需要更改:spring-doc.cadn.net.cn

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

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