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

OAuth 迁移

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

更改默认值oauth2Login()当局

在 Spring Security 5 中,默认的GrantedAuthority提供给使用 OAuth2 或 OpenID Connect 1.0 提供程序进行身份验证的用户(通过oauth2Login()) 是ROLE_USER.spring-doc.cadn.net.cn

有关更多信息,请参阅映射用户权限spring-doc.cadn.net.cn

在 Spring Security 6 中,授予使用 OAuth2 提供者进行身份验证的用户的默认权限是OAUTH2_USER. 授予使用 OpenID Connect 1.0 提供程序进行身份验证的用户的默认权限是OIDC_USER. 这些默认值允许更清楚地区分已使用 OAuth2 或 OpenID Connect 1.0 提供者进行身份验证的用户。spring-doc.cadn.net.cn

如果您使用的是授权规则或表达式(例如hasRole("USER")hasAuthority("ROLE_USER")要使用此特定权限授权用户,Spring Security 6 中的新默认值将影响您的应用程序。spring-doc.cadn.net.cn

要选择新的 Spring Security 6 默认值,可以使用以下配置。spring-doc.cadn.net.cn

使用 6.0 默认值配置 oauth2Login()
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
	http
		// ...
		.oauth2Login((oauth2Login) -> oauth2Login
			.userInfoEndpoint((userInfo) -> userInfo
				.userAuthoritiesMapper(grantedAuthoritiesMapper())
			)
		);
	return http.build();
}

private GrantedAuthoritiesMapper grantedAuthoritiesMapper() {
	return (authorities) -> {
		Set<GrantedAuthority> mappedAuthorities = new HashSet<>();

		authorities.forEach((authority) -> {
			GrantedAuthority mappedAuthority;

			if (authority instanceof OidcUserAuthority) {
				OidcUserAuthority userAuthority = (OidcUserAuthority) authority;
				mappedAuthority = new OidcUserAuthority(
					"OIDC_USER", userAuthority.getIdToken(), userAuthority.getUserInfo());
			} else if (authority instanceof OAuth2UserAuthority) {
				OAuth2UserAuthority userAuthority = (OAuth2UserAuthority) authority;
				mappedAuthority = new OAuth2UserAuthority(
					"OAUTH2_USER", userAuthority.getAttributes());
			} else {
				mappedAuthority = authority;
			}

			mappedAuthorities.add(mappedAuthority);
		});

		return mappedAuthorities;
	};
}
@Bean
fun securityFilterChain(http: HttpSecurity): SecurityFilterChain {
	http {
		// ...
		oauth2Login {
			userInfoEndpoint {
				userAuthoritiesMapper = grantedAuthoritiesMapper()
			}
		}
	}
	return http.build()
}

private fun grantedAuthoritiesMapper(): GrantedAuthoritiesMapper {
	return GrantedAuthoritiesMapper { authorities ->
		authorities.map { authority ->
			when (authority) {
				is OidcUserAuthority ->
					OidcUserAuthority("OIDC_USER", authority.idToken, authority.userInfo)
				is OAuth2UserAuthority ->
					OAuth2UserAuthority("OAUTH2_USER", authority.attributes)
				else -> authority
			}
		}
	}
}
<http>
	<oauth2-login user-authorities-mapper-ref="userAuthoritiesMapper" ... />
</http>

选择退出步骤

如果配置新权限给您带来麻烦,您可以选择退出并显式使用 5.8 的 5.8 权限ROLE_USER使用以下配置。spring-doc.cadn.net.cn

使用 5.8 默认值配置 oauth2Login()
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
	http
		// ...
		.oauth2Login((oauth2Login) -> oauth2Login
			.userInfoEndpoint((userInfo) -> userInfo
				.userAuthoritiesMapper(grantedAuthoritiesMapper())
			)
		);
	return http.build();
}

private GrantedAuthoritiesMapper grantedAuthoritiesMapper() {
	return (authorities) -> {
		Set<GrantedAuthority> mappedAuthorities = new HashSet<>();

		authorities.forEach((authority) -> {
			GrantedAuthority mappedAuthority;

			if (authority instanceof OidcUserAuthority) {
				OidcUserAuthority userAuthority = (OidcUserAuthority) authority;
				mappedAuthority = new OidcUserAuthority(
					"ROLE_USER", userAuthority.getIdToken(), userAuthority.getUserInfo());
			} else if (authority instanceof OAuth2UserAuthority) {
				OAuth2UserAuthority userAuthority = (OAuth2UserAuthority) authority;
				mappedAuthority = new OAuth2UserAuthority(
					"ROLE_USER", userAuthority.getAttributes());
			} else {
				mappedAuthority = authority;
			}

			mappedAuthorities.add(mappedAuthority);
		});

		return mappedAuthorities;
	};
}
@Bean
fun securityFilterChain(http: HttpSecurity): SecurityFilterChain {
	http {
		// ...
		oauth2Login {
			userInfoEndpoint {
				userAuthoritiesMapper = grantedAuthoritiesMapper()
			}
		}
	}
	return http.build()
}

private fun grantedAuthoritiesMapper(): GrantedAuthoritiesMapper {
	return GrantedAuthoritiesMapper { authorities ->
		authorities.map { authority ->
			when (authority) {
				is OidcUserAuthority ->
					OidcUserAuthority("ROLE_USER", authority.idToken, authority.userInfo)
				is OAuth2UserAuthority ->
					OAuth2UserAuthority("ROLE_USER", authority.attributes)
				else -> authority
			}
		}
	}
}
<http>
	<oauth2-login user-authorities-mapper-ref="userAuthoritiesMapper" ... />
</http>

解决 OAuth2 客户端弃用问题

在 Spring Security 6 中,已弃用的类和方法已从 OAuth2 客户端中删除。 下面列出了每个弃用版本以及直接替换版本。spring-doc.cadn.net.cn

ServletOAuth2AuthorizedClientExchangeFilterFunction

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

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

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

OidcUserInfo

方法phoneNumberVerified(String)可以替换为phoneNumberVerified(Boolean).spring-doc.cadn.net.cn

OAuth2AuthorizedClientArgumentResolver

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

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

ClaimAccessor

方法containsClaim(…​)可以替换为hasClaim(…​).spring-doc.cadn.net.cn

OidcClientInitiatedLogoutSuccessHandler

方法setPostLogoutRedirectUri(URI)可以替换为setPostLogoutRedirectUri(String).spring-doc.cadn.net.cn

HttpSessionOAuth2AuthorizationRequestRepository

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

AuthorizationRequestRepository

方法removeAuthorizationRequest(HttpServletRequest)可以替换为removeAuthorizationRequest(HttpServletRequest, HttpServletResponse).spring-doc.cadn.net.cn

ClientRegistration

方法getRedirectUriTemplate()可以替换为getRedirectUri().spring-doc.cadn.net.cn

ClientRegistration.Builder

方法redirectUriTemplate(…​)可以替换为redirectUri(…​).spring-doc.cadn.net.cn

AbstractOAuth2AuthorizationGrantRequest

构造函数AbstractOAuth2AuthorizationGrantRequest(AuthorizationGrantType)可以替换为AbstractOAuth2AuthorizationGrantRequest(AuthorizationGrantType, ClientRegistration).spring-doc.cadn.net.cn

ClientAuthenticationMethod

static 字段BASIC可以替换为CLIENT_SECRET_BASIC.spring-doc.cadn.net.cn

static 字段POST可以替换为CLIENT_SECRET_POST.spring-doc.cadn.net.cn

OAuth2AccessTokenResponseHttpMessageConverter

该领域tokenResponseConverter没有直接替代。spring-doc.cadn.net.cn

方法setTokenResponseConverter(…​)可以替换为setAccessTokenResponseConverter(…​).spring-doc.cadn.net.cn

该领域tokenResponseParametersConverter没有直接替代。spring-doc.cadn.net.cn

方法setTokenResponseParametersConverter(…​)可以替换为setAccessTokenResponseParametersConverter(…​).spring-doc.cadn.net.cn

NimbusAuthorizationCodeTokenResponseClient

NimbusAuthorizationCodeTokenResponseClient可以替换为DefaultAuthorizationCodeTokenResponseClient.spring-doc.cadn.net.cn

NimbusJwtDecoderJwkSupport

NimbusJwtDecoderJwkSupport可以替换为NimbusJwtDecoderJwtDecoders.spring-doc.cadn.net.cn

ImplicitGrantConfigurer

ImplicitGrantConfigurer没有直接替代。spring-doc.cadn.net.cn

使用implicit不建议使用授权类型,并且在 Spring Security 6 中删除了所有相关支持。spring-doc.cadn.net.cn

AuthorizationGrantType

static 字段IMPLICIT没有直接替代。spring-doc.cadn.net.cn

使用implicit不建议使用授权类型,并且在 Spring Security 6 中删除了所有相关支持。spring-doc.cadn.net.cn

OAuth2AuthorizationResponseType

static 字段TOKEN没有直接替代。spring-doc.cadn.net.cn

使用implicit不建议使用授权类型,并且在 Spring Security 6 中删除了所有相关支持。spring-doc.cadn.net.cn

OAuth2AuthorizationRequest

static 方法implicit()没有直接替代。spring-doc.cadn.net.cn

使用implicit不建议使用授权类型,并且在 Spring Security 6 中删除了所有相关支持。spring-doc.cadn.net.cn

地址JwtAuthenticationConverter折旧

方法extractAuthorities将被删除。 而不是扩展JwtAuthenticationConverter,请提供自定义授权转换器JwtAuthenticationConverter#setJwtGrantedAuthoritiesConverter.spring-doc.cadn.net.cn