| 本站(springdoc.cn)中的内容来源于 spring.io ,原始版权归属于 spring.io。由 springboot.io - Spring Boot中文社区 进行翻译,整理。可供个人学习、研究,未经许可,不得进行任何转载、商用或与之相关的行为。 商标声明:Spring 是 Pivotal Software, Inc. 在美国以及其他国家的商标。 | 
默配置
OAuth2AuthorizationServerConfiguration 是一个 @Configuration,为OAuth2授权服务器提供最小的默认配置。
OAuth2AuthorizationServerConfiguration 使用 OAuth2AuthorizationServerConfigurer 来应用默认配置,并注册了一个由支持OAuth2授权服务器的所有基础设施组件组成的 SecurityFilterChain  @Bean。
| OAuth2AuthorizationServerConfiguration.applyDefaultSecurity(HttpSecurity)是一个方便(静态)的实用方法,它将默认的 OAuth2 security configuration 应用到HttpSecurity。 | 
OAuth2 授权服务器 SecurityFilterChain @Bean 配置了以下默认协议端点。
| 只有在注册了 JWKSource<SecurityContext>@Bean时,才会配置JWK Set端点。 | 
下面的例子显示了如何使用 OAuth2AuthorizationServerConfiguration 来应用最小的默认配置。
@Configuration
@Import(OAuth2AuthorizationServerConfiguration.class)
public class AuthorizationServerConfig {
	@Bean
	public RegisteredClientRepository registeredClientRepository() {
		List<RegisteredClient> registrations = ...
		return new InMemoryRegisteredClientRepository(registrations);
	}
	@Bean
	public JWKSource<SecurityContext> jwkSource() {
		RSAKey rsaKey = ...
		JWKSet jwkSet = new JWKSet(rsaKey);
		return (jwkSelector, securityContext) -> jwkSelector.select(jwkSet);
	}
}
| authorization_code 的授予 需要资源所有者经过认证。因此,除了默认的OAuth2安全配置外,还必须配置一个用户认证机制。 | 
OpenID Connect 1.0 在默认配置中被禁用。下面的例子显示了如何通过初始化 OidcConfigurer 来启用OpenID Connect 1.0。
@Bean
public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception {
	OAuth2AuthorizationServerConfiguration.applyDefaultSecurity(http);
	http.getConfigurer(OAuth2AuthorizationServerConfigurer.class)
		.oidc(Customizer.withDefaults());	// Initialize `OidcConfigurer`
	return http.build();
}
除了默认的协议端点外,OAuth2授权服务器 SecurityFilterChain @Bean 还配置了以下OpenID Connect 1.0协议端点。
| OpenID Connect 1.0客户端注册端点 默认是禁用的,因为许多部署不需要动态客户端注册。 | 
| OAuth2AuthorizationServerConfiguration.jwtDecoder(JWKSource<SecurityContext>)是一个方便(静态)的实用方法,可以用来注册一个JwtDecoder@Bean,它 是 OpenID Connect 1.0 UserInfo端点 和 OpenID Connect 1.0 Client Registration 端点 的必要条件。 | 
下面的例子展示了如何注册一个 JwtDecoder @Bean。
@Bean
public JwtDecoder jwtDecoder(JWKSource<SecurityContext> jwkSource) {
	return OAuth2AuthorizationServerConfiguration.jwtDecoder(jwkSource);
}
OAuth2AuthorizationServerConfiguration 的主要意图是提供一个方便的方法来应用OAuth2授权服务器的最小默认配置。然而,在大多数情况下,需要对配置进行定制。
自定义配置
OAuth2AuthorizationServerConfigurer 提供了完全定制OAuth2授权服务器的 security configuration 的能力。它可以让你指定使用的核心组件—例如 RegisteredClientRepository、OAuth2AuthorizationService、OAuth2TokenGenerator 和其他。此外,它可以让你定制协议端点的请求处理逻辑—例如,授权端点、令牌端点、令牌内省端点 等。
OAuth2AuthorizationServerConfigurer 提供以下配置选项。
@Bean
public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception {
	OAuth2AuthorizationServerConfigurer authorizationServerConfigurer =
		new OAuth2AuthorizationServerConfigurer();
	http.apply(authorizationServerConfigurer);
	authorizationServerConfigurer
		.registeredClientRepository(registeredClientRepository) (1)
		.authorizationService(authorizationService) (2)
		.authorizationConsentService(authorizationConsentService)   (3)
		.authorizationServerSettings(authorizationServerSettings) (4)
		.tokenGenerator(tokenGenerator) (5)
		.clientAuthentication(clientAuthentication -> { })  (6)
		.authorizationEndpoint(authorizationEndpoint -> { })    (7)
		.tokenEndpoint(tokenEndpoint -> { })    (8)
		.tokenIntrospectionEndpoint(tokenIntrospectionEndpoint -> { })  (9)
		.tokenRevocationEndpoint(tokenRevocationEndpoint -> { })    (10)
		.authorizationServerMetadataEndpoint(authorizationServerMetadataEndpoint -> { })    (11)
		.oidc(oidc -> oidc
			.providerConfigurationEndpoint(providerConfigurationEndpoint -> { })    (12)
			.userInfoEndpoint(userInfoEndpoint -> { })  (13)
			.clientRegistrationEndpoint(clientRegistrationEndpoint -> { })  (14)
		);
	return http.build();
}
| 1 | registeredClientRepository():RegisteredClientRepository(必需的) 用于管理新的和现有的客户。 | 
| 2 | authorizationService(): 用于管理新的和现有的授权的OAuth2AuthorizationService。 | 
| 3 | authorizationConsentService():OAuth2AuthorizationConsentService,用于管理新的和现有的授权许可(Consent)。 | 
| 4 | authorizationServerSettings(): 用于自定义OAuth2授权服务器的 configuration setting 的AuthorizationServerSettings(必需的)。 | 
| 5 | tokenGenerator():OAuth2TokenGenerator,用于生成OAuth2授权服务器支持的令牌。 | 
| 6 | clientAuthentication():  OAuth2客户端认证的configurer。 | 
| 7 | authorizationEndpoint(): OAuth2授权端点 的 configurer。 | 
| 8 | tokenEndpoint(): OAuth2令牌端点 的 configurer。 | 
| 9 | tokenIntrospectionEndpoint(): OAuth2 Token Introspection endpoint 端点的 configurer。 | 
| 10 | tokenRevocationEndpoint(): OAuth2 Token Revocation 端点 的 configurer。 | 
| 11 | authorizationServerMetadataEndpoint(): OAuth2授权服务器元数据端点 的 configurer。 | 
| 12 | providerConfigurationEndpoint(): OpenID Connect 1.0 Provider 配置端点 的 configurer。 | 
| 13 | userInfoEndpoint(): OpenID Connect 1.0 UserInfo 端点 的 configurer。 | 
| 14 | clientRegistrationEndpoint(): OpenID Connect 1.0 客户端注册端点 的 configurer。 | 
配置 Authorization Server Setting
AuthorizationServerSettings 包含 OAuth2 授权服务器的 configuration setting。它指定了协议端点的 URI 以及 issuer identifier。协议端点的默认URI如下。
public final class AuthorizationServerSettings extends AbstractSettings {
	...
	public static Builder builder() {
		return new Builder()
			.authorizationEndpoint("/oauth2/authorize")
			.tokenEndpoint("/oauth2/token")
			.tokenIntrospectionEndpoint("/oauth2/introspect")
			.tokenRevocationEndpoint("/oauth2/revoke")
			.jwkSetEndpoint("/oauth2/jwks")
			.oidcUserInfoEndpoint("/userinfo")
			.oidcClientRegistrationEndpoint("/connect/register");
	}
	...
}
| AuthorizationServerSettings是一个必需的组件。 | 
| @Import(OAuth2AuthorizationServerConfiguration.class)自动注册了一个AuthorizationServerSettings@Bean,如果没有提供的话。 | 
下面的例子展示了如何定制配置设置并注册一个 AuthorizationServerSettings @Bean。
@Bean
public AuthorizationServerSettings authorizationServerSettings() {
	return AuthorizationServerSettings.builder()
		.issuer("https://example.com")
		.authorizationEndpoint("/oauth2/v1/authorize")
		.tokenEndpoint("/oauth2/v1/token")
		.tokenIntrospectionEndpoint("/oauth2/v1/introspect")
		.tokenRevocationEndpoint("/oauth2/v1/revoke")
		.jwkSetEndpoint("/oauth2/v1/jwks")
		.oidcUserInfoEndpoint("/connect/v1/userinfo")
		.oidcClientRegistrationEndpoint("/connect/v1/register")
		.build();
}
AuthorizationServerContext 是一个持有授权服务器运行环境信息的上下文对象。它提供了对 AuthorizationServerSettings 和 “current” issuer identifier 的访问。
| 如果 issuer identifier 没有在 AuthorizationServerSettings.builder().issuer(String)中配置,它将从当前请求中解析。 | 
| AuthorizationServerContext可以通过AuthorizationServerContextHolder访问,它通过使用ThreadLocal将其与当前请求线程联系起来。 | 
配置客户端认证
OAuth2ClientAuthenticationConfigurer 提供了定制 OAuth2客户端认证 的能力。它定义了一些扩展点,让你自定义客户端认证请求的预处理、主要处理和后处理逻辑。
OAuth2ClientAuthenticationConfigurer 提供以下配置选项。
@Bean
public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception {
	OAuth2AuthorizationServerConfigurer authorizationServerConfigurer =
		new OAuth2AuthorizationServerConfigurer();
	http.apply(authorizationServerConfigurer);
	authorizationServerConfigurer
		.clientAuthentication(clientAuthentication ->
			clientAuthentication
				.authenticationConverter(authenticationConverter)   (1)
				.authenticationConverters(authenticationConvertersConsumer) (2)
				.authenticationProvider(authenticationProvider) (3)
				.authenticationProviders(authenticationProvidersConsumer)   (4)
				.authenticationSuccessHandler(authenticationSuccessHandler) (5)
				.errorResponseHandler(errorResponseHandler) (6)
		);
	return http.build();
}
| 1 | authenticationConverter(): 添加一个AuthenticationConverter(预处理器),当试图从HttpServletRequest中提取客户端凭证到OAuth2ClientAuthenticationToken的实例时使用。 | 
| 2 | authenticationConverters(): 设置Consumer,提供对默认和(可选)添加的AuthenticationConverterList的访问,允许添加、删除或定制特定的AuthenticationConverter的能力。 | 
| 3 | authenticationProvider(): 添加一个用于验证OAuth2ClientAuthenticationToken的AuthenticationProvider(主处理器)。 | 
| 4 | authenticationProviders(): 设置Consumer,提供对默认和(可选)添加的AuthenticationProviderList的访问,允许添加、删除或定制特定的AuthenticationProvider。 | 
| 5 | authenticationSuccessHandler():AuthenticationSuccessHandler(后处理器),用于处理成功的客户端认证,并将OAuth2ClientAuthenticationToken与SecurityContext相关联。 | 
| 6 | errorResponseHandler():AuthenticationFailureHandler(后处理器),用于处理客户端认证失败并返回OAuth2Error响应。 | 
OAuth2ClientAuthenticationConfigurer 配置 OAuth2ClientAuthenticationFilter 并将其注册到OAuth2授权服务器 SecurityFilterChain @Bean。OAuth2ClientAuthenticationFilter 是处理客户端认证请求的过滤器。
默认情况下,OAuth2令牌端点、OAuth2令牌内省(Introspection)端点和 OAuth2令牌撤销端点 都需要客户端认证。支持的客户端认证方法有 client_secret_basic、client_secret_post、private_key_jwt、client_secret_jwt 和 none(公共客户端)。
OAuth2ClientAuthenticationFilter 配置的默认值如下。
- 
AuthenticationConverter— 一个由JwtClientAssertionAuthenticationConverter、ClientSecretBasicAuthenticationConverter、ClientSecretPostAuthenticationConverter和PublicClientAuthenticationConverter组成的DelegatingAuthenticationConverter。
- 
AuthenticationManager— 一个由JwtClientAssertionAuthenticationProvider、ClientSecretAuthenticationProvider和PublicClientAuthenticationProvider组成的AuthenticationManager。
- 
AuthenticationSuccessHandler— 一个内部实现,将 "已认证" 的OAuth2ClientAuthenticationToken(当前Authentication)与SecurityContext相关联。
- 
AuthenticationFailureHandler— 一个内部实现,使用与OAuth2AuthenticationException相关的OAuth2Error来返回OAuth2错误响应。
自定义Jwt客户端断言(Assertion)验证
JwtClientAssertionDecoderFactory.DEFAULT_JWT_VALIDATOR_FACTORY 是默认工厂,为指定的 RegisteredClient 提供 OAuth2TokenValidator<Jwt>,用于验证Jwt客户端断言(assertion)的 iss、sub、aud、exp 和 nbf claim。
JwtClientAssertionDecoderFactory 为 setJwtValidatorFactory() 提供了通过提供 Function<RegisteredClient, OAuth2TokenValidator<Jwt> 类型的自定义工厂来覆盖默认 Jwt 客户端断言(assertion)验证的能力。
| JwtClientAssertionDecoderFactory是JwtClientAssertionAuthenticationProvider使用的默认JwtDecoderFactory,它为指定的RegisteredClient提供一个JwtDecoder,用于在OAuth2客户端认证过程中认证Jwt Bearer Token。 | 
定制 JwtClientAssertionDecoderFactory 的一个常见用例是验证Jwt客户端断言(assertion)中的额外claim。
下面的例子展示了如何用一个定制的 JwtClientAssertionDecoderFactory 来配置 JwtClientAssertionAuthenticationProvider,它可以验证 Jwt 客户端断言(assertion)中的一个额外claim。
@Bean
public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception {
	OAuth2AuthorizationServerConfigurer authorizationServerConfigurer =
		new OAuth2AuthorizationServerConfigurer();
	http.apply(authorizationServerConfigurer);
	authorizationServerConfigurer
		.clientAuthentication(clientAuthentication ->
			clientAuthentication
				.authenticationProviders(configureJwtClientAssertionValidator())
		);
	return http.build();
}
private Consumer<List<AuthenticationProvider>> configureJwtClientAssertionValidator() {
	return (authenticationProviders) ->
		authenticationProviders.forEach((authenticationProvider) -> {
			if (authenticationProvider instanceof JwtClientAssertionAuthenticationProvider) {
				// Customize JwtClientAssertionDecoderFactory
				JwtClientAssertionDecoderFactory jwtDecoderFactory = new JwtClientAssertionDecoderFactory();
				Function<RegisteredClient, OAuth2TokenValidator<Jwt>> jwtValidatorFactory = (registeredClient) ->
					new DelegatingOAuth2TokenValidator<>(
						// Use default validators
						JwtClientAssertionDecoderFactory.DEFAULT_JWT_VALIDATOR_FACTORY.apply(registeredClient),
						// Add custom validator
						new JwtClaimValidator<>("claim", "value"::equals));
				jwtDecoderFactory.setJwtValidatorFactory(jwtValidatorFactory);
				((JwtClientAssertionAuthenticationProvider) authenticationProvider)
					.setJwtDecoderFactory(jwtDecoderFactory);
			}
		});
}