跳到主要内容
版本:7.0.2

配置模型

DeepSeek V3 中英对照 Configuration Model

默认配置

OAuth2AuthorizationServerConfiguration 是一个 @Configuration,它为 OAuth2 授权服务器提供了最简化的默认配置。

OAuth2AuthorizationServerConfiguration 使用 OAuth2AuthorizationServerConfigurer 来应用默认配置,并注册一个由支持 OAuth2 授权服务器的所有基础设施组件组成的 SecurityFilterChain @Bean

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);
}

}
important

授权码模式要求资源所有者(用户)必须经过身份认证。因此,除了默认的 OAuth2 安全配置外,必须额外配置一个用户认证机制。

OpenID Connect 1.0 在默认配置中处于禁用状态。以下示例展示了如何通过初始化 OidcConfigurer 来启用 OpenID Connect 1.0:

@Bean
public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception {
http
.oauth2AuthorizationServer((authorizationServer) ->
authorizationServer
.oidc(Customizer.withDefaults()) // Initialize `OidcConfigurer`
);
return http.build();
}

除了默认的协议端点外,OAuth2授权服务器的SecurityFilterChain @Bean还配置了以下OpenID Connect 1.0协议端点:

备注

默认情况下,OpenID Connect 1.0 客户端注册端点 是禁用的。

提示

OAuth2AuthorizationServerConfiguration.jwtDecoder(JWKSource<SecurityContext>) 是一个便捷的(static)工具方法,可用于注册一个 JwtDecoder @Bean,该 Bean 是 OpenID Connect 1.0 UserInfo 端点OpenID Connect 1.0 客户端注册端点 必需 的。

以下示例展示了如何注册一个 JwtDecoder @Bean

@Bean
public JwtDecoder jwtDecoder(JWKSource<SecurityContext> jwkSource) {
return OAuth2AuthorizationServerConfiguration.jwtDecoder(jwkSource);
}

OAuth2AuthorizationServerConfiguration 的主要目的是提供一个便捷的方法来应用 OAuth2 授权服务器的最小默认配置。然而,在大多数情况下,都需要对配置进行自定义。

自定义配置

OAuth2AuthorizationServerConfigurer 提供了完全自定义 OAuth2 授权服务器安全配置的能力。它允许您指定要使用的核心组件——例如,RegisteredClientRepositoryOAuth2AuthorizationServiceOAuth2TokenGenerator 等。此外,它还允许您自定义协议端点的请求处理逻辑——例如,授权端点设备授权端点设备验证端点令牌端点令牌内省端点 等。

OAuth2AuthorizationServerConfigurer 提供了以下配置选项:

@Bean
public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception {
http
.oauth2AuthorizationServer((authorizationServer) ->
authorizationServer
.registeredClientRepository(registeredClientRepository) 1
.authorizationService(authorizationService) 2
.authorizationConsentService(authorizationConsentService) 3
.authorizationServerSettings(authorizationServerSettings) 4
.tokenGenerator(tokenGenerator) 5
.clientAuthentication(clientAuthentication -> { }) 6
.authorizationEndpoint(authorizationEndpoint -> { }) 7
.pushedAuthorizationRequestEndpoint(pushedAuthorizationRequestEndpoint -> { }) 8
.deviceAuthorizationEndpoint(deviceAuthorizationEndpoint -> { }) 9
.deviceVerificationEndpoint(deviceVerificationEndpoint -> { }) 10
.tokenEndpoint(tokenEndpoint -> { }) 11
.tokenIntrospectionEndpoint(tokenIntrospectionEndpoint -> { }) 12
.tokenRevocationEndpoint(tokenRevocationEndpoint -> { }) 13
.clientRegistrationEndpoint(clientRegistrationEndpoint -> { }) 14
.authorizationServerMetadataEndpoint(authorizationServerMetadataEndpoint -> { }) 15
.oidc(oidc -> oidc
.providerConfigurationEndpoint(providerConfigurationEndpoint -> { }) 16
.logoutEndpoint(logoutEndpoint -> { }) 17
.userInfoEndpoint(userInfoEndpoint -> { }) 18
.clientRegistrationEndpoint(clientRegistrationEndpoint -> { }) 19
)
);

return http.build();
}

配置授权服务器设置

AuthorizationServerSettings 包含 OAuth2 授权服务器的配置设置。它指定协议端点的 URI 以及发行者标识符。协议端点的默认 URI 如下:

public final class AuthorizationServerSettings extends AbstractSettings {

...

public static Builder builder() {
return new Builder()
.authorizationEndpoint("/oauth2/authorize")
.pushedAuthorizationRequestEndpoint("/oauth2/par")
.deviceAuthorizationEndpoint("/oauth2/device_authorization")
.deviceVerificationEndpoint("/oauth2/device_verification")
.tokenEndpoint("/oauth2/token")
.tokenIntrospectionEndpoint("/oauth2/introspect")
.tokenRevocationEndpoint("/oauth2/revoke")
.clientRegistrationEndpoint("/oauth2/register")
.jwkSetEndpoint("/oauth2/jwks")
.oidcLogoutEndpoint("/connect/logout")
.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")
.pushedAuthorizationRequestEndpoint("/oauth2/v1/par")
.deviceAuthorizationEndpoint("/oauth2/v1/device_authorization")
.deviceVerificationEndpoint("/oauth2/v1/device_verification")
.tokenEndpoint("/oauth2/v1/token")
.tokenIntrospectionEndpoint("/oauth2/v1/introspect")
.tokenRevocationEndpoint("/oauth2/v1/revoke")
.clientRegistrationEndpoint("/oauth2/v1/register")
.jwkSetEndpoint("/oauth2/v1/jwks")
.oidcLogoutEndpoint("/connect/v1/logout")
.oidcUserInfoEndpoint("/connect/v1/userinfo")
.oidcClientRegistrationEndpoint("/connect/v1/register")
.build();
}

AuthorizationServerContext 是一个上下文对象,用于存储授权服务器运行时环境的信息。它提供对 AuthorizationServerSettings 以及“当前”颁发者标识符的访问。

备注

如果未在 AuthorizationServerSettings.builder().issuer(String) 中配置颁发者标识符,则会从当前请求中解析。

备注

AuthorizationServerContext 可通过 AuthorizationServerContextHolder 访问,后者通过 ThreadLocal 将其与当前请求线程关联。

配置客户端认证

OAuth2ClientAuthenticationConfigurer 提供了自定义 OAuth2 客户端认证 的能力。它定义了多个扩展点,允许您自定义客户端认证请求的预处理、主处理和后处理逻辑。

OAuth2ClientAuthenticationConfigurer 提供以下配置选项:

@Bean
public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception {
http
.oauth2AuthorizationServer((authorizationServer) ->
authorizationServer
.clientAuthentication(clientAuthentication ->
clientAuthentication
.authenticationConverter(authenticationConverter) 1
.authenticationConverters(authenticationConvertersConsumer) 2
.authenticationProvider(authenticationProvider) 3
.authenticationProviders(authenticationProvidersConsumer) 4
.authenticationSuccessHandler(authenticationSuccessHandler) 5
.errorResponseHandler(errorResponseHandler) 6
)
);

return http.build();
}
  • authenticationConverter(): 添加一个 AuthenticationConverter预处理器),用于在尝试从 HttpServletRequest 中提取客户端凭据时,将其转换为 OAuth2ClientAuthenticationToken 实例。

  • authenticationConverters(): 设置一个 Consumer,该 Consumer 提供对默认及(可选)添加的 AuthenticationConverter 列表的访问,允许添加、移除或自定义特定的 AuthenticationConverter

  • authenticationProvider(): 添加一个 AuthenticationProvider主处理器),用于对 OAuth2ClientAuthenticationToken 进行身份验证。

  • authenticationProviders(): 设置一个 Consumer,该 Consumer 提供对默认及(可选)添加的 AuthenticationProvider 列表的访问,允许添加、移除或自定义特定的 AuthenticationProvider

  • authenticationSuccessHandler(): 用于处理成功的客户端身份验证并将 OAuth2ClientAuthenticationToken 关联到 SecurityContextAuthenticationSuccessHandler后处理器)。

  • errorResponseHandler(): 用于处理失败的客户端身份验证并返回 OAuth2Error 响应AuthenticationFailureHandler后处理器)。

OAuth2ClientAuthenticationConfigurer 用于配置 OAuth2ClientAuthenticationFilter 并将其注册到 OAuth2 授权服务器的 SecurityFilterChain @Bean 中。OAuth2ClientAuthenticationFilter 是处理客户端认证请求的 Filter

默认情况下,OAuth2 令牌端点OAuth2 令牌内省端点OAuth2 令牌撤销端点 都需要客户端认证。支持的客户端认证方法包括 client_secret_basicclient_secret_postprivate_key_jwtclient_secret_jwttls_client_authself_signed_tls_client_auth 以及 none(公共客户端)。

OAuth2ClientAuthenticationFilter 配置了以下默认设置:

  • **AuthenticationConverter** — 一个由 JwtClientAssertionAuthenticationConverterX509ClientCertificateAuthenticationConverterClientSecretBasicAuthenticationConverterClientSecretPostAuthenticationConverterPublicClientAuthenticationConverter 组成的 DelegatingAuthenticationConverter

  • **AuthenticationManager** — 一个由 JwtClientAssertionAuthenticationProviderX509ClientCertificateAuthenticationProviderClientSecretAuthenticationProviderPublicClientAuthenticationProvider 组成的 AuthenticationManager

  • **AuthenticationSuccessHandler** — 一个内部实现,它将“已认证”的 OAuth2ClientAuthenticationToken(当前的 Authentication)与 SecurityContext 关联起来。

  • **AuthenticationFailureHandler** — 一个内部实现,它使用与 OAuth2AuthenticationException 关联的 OAuth2Error 来返回 OAuth2 错误响应。

自定义 JWT 客户端断言验证

JwtClientAssertionDecoderFactory.DEFAULT_JWT_VALIDATOR_FACTORY 是默认的工厂,它为指定的 RegisteredClient 提供 OAuth2TokenValidator<Jwt>,用于验证 Jwt 客户端断言的 isssubaudexpnbf 声明。

JwtClientAssertionDecoderFactory 提供了通过向 setJwtValidatorFactory() 方法提供类型为 Function<RegisteredClient, OAuth2TokenValidator<Jwt>> 的自定义工厂,来覆盖默认 Jwt 客户端断言验证的能力。

备注

JwtClientAssertionDecoderFactoryJwtClientAssertionAuthenticationProvider 使用的默认 JwtDecoderFactory,它为指定的 RegisteredClient 提供一个 JwtDecoder,并在 OAuth2 客户端认证期间用于验证 Jwt Bearer Token。

自定义 JwtClientAssertionDecoderFactory 的一个常见用例是验证 Jwt 客户端断言中的附加声明。

以下示例展示了如何配置 JwtClientAssertionAuthenticationProvider,并使用自定义的 JwtClientAssertionDecoderFactory 来验证 Jwt 客户端断言中的附加声明:

@Bean
public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception {
http
.oauth2AuthorizationServer((authorizationServer) ->
authorizationServer
.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);
}
});
}

自定义双向TLS客户端认证

X509ClientCertificateAuthenticationProvider 用于在 OAuth2 客户端认证过程中,当使用 ClientAuthenticationMethod.TLS_CLIENT_AUTHClientAuthenticationMethod.SELF_SIGNED_TLS_CLIENT_AUTH 方法时,对接收到的客户端 X509Certificate 链进行认证。它还包含一个*"证书验证器"*,用于在 TLS 握手成功完成后验证客户端 X509Certificate 的内容。

PKI 相互TLS方法

对于PKI双向TLS(ClientAuthenticationMethod.TLS_CLIENT_AUTH)认证方式,其默认的证书验证器实现会将客户端X509Certificate的主题可分辨名称与RegisteredClient.getClientSettings.getX509CertificateSubjectDN()设置进行比对验证。

若需验证客户端 X509Certificate 的其他属性,例如主题备用名称(SAN)条目,以下示例展示了如何通过自定义证书验证器实现来配置 X509ClientCertificateAuthenticationProvider

@Bean
public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception {
http
.oauth2AuthorizationServer((authorizationServer) ->
authorizationServer
.clientAuthentication(clientAuthentication ->
clientAuthentication
.authenticationProviders(configureX509ClientCertificateVerifier())
)
);

return http.build();
}

private Consumer<List<AuthenticationProvider>> configureX509ClientCertificateVerifier() {
return (authenticationProviders) ->
authenticationProviders.forEach((authenticationProvider) -> {
if (authenticationProvider instanceof X509ClientCertificateAuthenticationProvider) {
Consumer<OAuth2ClientAuthenticationContext> certificateVerifier = (clientAuthenticationContext) -> {
OAuth2ClientAuthenticationToken clientAuthentication = clientAuthenticationContext.getAuthentication();
RegisteredClient registeredClient = clientAuthenticationContext.getRegisteredClient();
X509Certificate[] clientCertificateChain = (X509Certificate[]) clientAuthentication.getCredentials();
X509Certificate clientCertificate = clientCertificateChain[0];

// TODO Verify Subject Alternative Name (SAN) entry

};

((X509ClientCertificateAuthenticationProvider) authenticationProvider)
.setCertificateVerifier(certificateVerifier);
}
});
}

自签名证书双向TLS方法

对于自签名证书双向TLS(ClientAuthenticationMethod.SELF_SIGNED_TLS_CLIENT_AUTH)认证方式,证书验证器的默认实现将通过配置项 RegisteredClient.getClientSettings.getJwkSetUrl() 获取客户端的 JSON Web 密钥集,并期望在其中找到与 TLS 握手过程中接收到的客户端 X509Certificate 相匹配的证书。

备注

RegisteredClient.getClientSettings.getJwkSetUrl() 设置用于通过 JSON Web Key (JWK) 集检索客户端的证书。证书由 JWK 集中单个 JWK 的 x5c 参数表示。

客户端证书绑定访问令牌

当在令牌端点使用双向TLS客户端认证时,授权服务器能够将颁发的访问令牌与客户端的X509Certificate绑定。该绑定通过计算客户端X509Certificate的 SHA-256 指纹,并将该指纹与访问令牌关联来实现。例如,一个 JWT 访问令牌会在顶层的cnf(确认方法)声明中包含一个x5t#S256声明,该声明包含了X509Certificate指纹。

将访问令牌绑定到客户端的X509Certificate,能够在访问受保护资源时实现持有证明机制。例如,受保护资源会获取在双向TLS认证期间使用的客户端X509Certificate,然后验证证书指纹是否与访问令牌关联的x5t#S256声明相匹配。

以下示例展示了如何为客户端启用证书绑定访问令牌:

RegisteredClient mtlsClient = RegisteredClient.withId(UUID.randomUUID().toString())
.clientId("mtls-client")
.clientAuthenticationMethod(ClientAuthenticationMethod.TLS_CLIENT_AUTH)
.authorizationGrantType(AuthorizationGrantType.CLIENT_CREDENTIALS)
.scope("scope-a")
.clientSettings(
ClientSettings.builder()
.x509CertificateSubjectDN("CN=mtls-client,OU=Spring Samples,O=Spring,C=US")
.build()
)
.tokenSettings(
TokenSettings.builder()
.x509CertificateBoundAccessTokens(true)
.build()
)
.build();