Advanced Configuration
HttpSecurity.oauth2Login()
提供了多个用于自定义 OAuth 2.0 Login 的配置选项。主要配置选项统筹到其协议端点对等体。
HttpSecurity.oauth2Login()
provides a number of configuration options for customizing OAuth 2.0 Login.
The main configuration options are grouped into their protocol endpoint counterparts.
例如,oauth2Login().authorizationEndpoint()
允许配置 Authorization Endpoint,而 oauth2Login().tokenEndpoint()
允许配置 Token Endpoint。
For example, oauth2Login().authorizationEndpoint()
allows configuring the Authorization Endpoint, whereas oauth2Login().tokenEndpoint()
allows configuring the Token Endpoint.
以下代码显示了一个示例:
The following code shows an example:
-
Java
-
Kotlin
@Configuration
@EnableWebSecurity
public class OAuth2LoginSecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.oauth2Login(oauth2 -> oauth2
.authorizationEndpoint(authorization -> authorization
...
)
.redirectionEndpoint(redirection -> redirection
...
)
.tokenEndpoint(token -> token
...
)
.userInfoEndpoint(userInfo -> userInfo
...
)
);
return http.build();
}
}
@Configuration
@EnableWebSecurity
class OAuth2LoginSecurityConfig {
@Bean
open fun filterChain(http: HttpSecurity): SecurityFilterChain {
http {
oauth2Login {
authorizationEndpoint {
...
}
redirectionEndpoint {
...
}
tokenEndpoint {
...
}
userInfoEndpoint {
...
}
}
}
return http.build()
}
}
oauth2Login()
DSL 的主要目标是与规范中定义的命名紧密对齐。
The main goal of the oauth2Login()
DSL was to closely align with the naming, as defined in the specifications.
OAuth 2.0 授权框架将 Protocol Endpoints 定义如下:
The OAuth 2.0 Authorization Framework defines the Protocol Endpoints as follows:
授权过程使用两个授权服务器端点(HTTP 资源):
The authorization process uses two authorization server endpoints (HTTP resources):
-
Authorization Endpoint: Used by the client to obtain authorization from the resource owner through user-agent redirection.
-
Token Endpoint: Used by the client to exchange an authorization grant for an access token, typically with client authentication.
授权过程还使用一个客户端端点:
The authorization process also uses one client endpoint:
-
Redirection Endpoint: Used by the authorization server to return responses that contain authorization credentials to the client through the resource owner user-agent.
OpenID Connect 核心 1.0 规范将 UserInfo Endpoint 定义如下:
The OpenID Connect Core 1.0 specification defines the UserInfo Endpoint as follows:
UserInfo 端点是一个 OAuth 2.0 受保护资源,返回有关经过身份验证的最终用户的信息。为了获得有关最终用户请求的信息,客户端使用通过 OpenID Connect Authentication 获得的访问令牌,向 UserInfo 端点发出请求。这些信息通常由一个 JSON 对象表示,该对象包含一系列用于信息的名称-值对。
The UserInfo Endpoint is an OAuth 2.0 Protected Resource that returns claims about the authenticated end-user. To obtain the requested claims about the end-user, the client makes a request to the UserInfo Endpoint by using an access token obtained through OpenID Connect Authentication. These claims are normally represented by a JSON object that contains a collection of name-value pairs for the claims.
以下代码显示了 oauth2Login()
DSL 可用的完整配置选项:
The following code shows the complete configuration options available for the oauth2Login()
DSL:
-
Java
-
Kotlin
@Configuration
@EnableWebSecurity
public class OAuth2LoginSecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.oauth2Login(oauth2 -> oauth2
.clientRegistrationRepository(this.clientRegistrationRepository())
.authorizedClientRepository(this.authorizedClientRepository())
.authorizedClientService(this.authorizedClientService())
.loginPage("/login")
.authorizationEndpoint(authorization -> authorization
.baseUri(this.authorizationRequestBaseUri())
.authorizationRequestRepository(this.authorizationRequestRepository())
.authorizationRequestResolver(this.authorizationRequestResolver())
)
.redirectionEndpoint(redirection -> redirection
.baseUri(this.authorizationResponseBaseUri())
)
.tokenEndpoint(token -> token
.accessTokenResponseClient(this.accessTokenResponseClient())
)
.userInfoEndpoint(userInfo -> userInfo
.userAuthoritiesMapper(this.userAuthoritiesMapper())
.userService(this.oauth2UserService())
.oidcUserService(this.oidcUserService())
)
);
return http.build();
}
}
@Configuration
@EnableWebSecurity
class OAuth2LoginSecurityConfig {
@Bean
open fun filterChain(http: HttpSecurity): SecurityFilterChain {
http {
oauth2Login {
clientRegistrationRepository = clientRegistrationRepository()
authorizedClientRepository = authorizedClientRepository()
authorizedClientService = authorizedClientService()
loginPage = "/login"
authorizationEndpoint {
baseUri = authorizationRequestBaseUri()
authorizationRequestRepository = authorizationRequestRepository()
authorizationRequestResolver = authorizationRequestResolver()
}
redirectionEndpoint {
baseUri = authorizationResponseBaseUri()
}
tokenEndpoint {
accessTokenResponseClient = accessTokenResponseClient()
}
userInfoEndpoint {
userAuthoritiesMapper = userAuthoritiesMapper()
userService = oauth2UserService()
oidcUserService = oidcUserService()
}
}
}
return http.build()
}
}
除了 oauth2Login()
DSL,还支持 XML 配置。
In addition to the oauth2Login()
DSL, XML configuration is also supported.
以下代码显示了 security namespace 中可用的完整配置选项:
The following code shows the complete configuration options available in the security namespace:
<http>
<oauth2-login client-registration-repository-ref="clientRegistrationRepository"
authorized-client-repository-ref="authorizedClientRepository"
authorized-client-service-ref="authorizedClientService"
authorization-request-repository-ref="authorizationRequestRepository"
authorization-request-resolver-ref="authorizationRequestResolver"
access-token-response-client-ref="accessTokenResponseClient"
user-authorities-mapper-ref="userAuthoritiesMapper"
user-service-ref="oauth2UserService"
oidc-user-service-ref="oidcUserService"
login-processing-url="/login/oauth2/code/*"
login-page="/login"
authentication-success-handler-ref="authenticationSuccessHandler"
authentication-failure-handler-ref="authenticationFailureHandler"
jwt-decoder-factory-ref="jwtDecoderFactory"/>
</http>
以下各节将详细介绍每个可用的配置选项:
The following sections go into more detail on each of the configuration options available:
OAuth 2.0 Login Page
默认情况下,OAuth 2.0 登录页面由 DefaultLoginPageGeneratingFilter
自动生成。默认登录页面显示每个已配置 OAuth 客户端及其 ClientRegistration.clientName
作为一个链接,它能够启动授权请求(或 OAuth 2.0 登录)。
By default, the OAuth 2.0 Login Page is auto-generated by the DefaultLoginPageGeneratingFilter
.
The default login page shows each configured OAuth Client with its ClientRegistration.clientName
as a link, which is capable of initiating the Authorization Request (or OAuth 2.0 Login).
要使 For |
每个 OAuth 客户端的链接目标默认为以下内容:
The link’s destination for each OAuth Client defaults to the following:
OAuth2AuthorizationRequestRedirectFilter.DEFAULT_AUTHORIZATION_REQUEST_BASE_URI + "/{registrationId}"
以下行为示例:
The following line shows an example:
<a href="/oauth2/authorization/google">Google</a>
若要覆盖默认登录页面,请配置 oauth2Login().loginPage()
和(可选)oauth2Login().authorizationEndpoint().baseUri()
。
To override the default login page, configure oauth2Login().loginPage()
and (optionally) oauth2Login().authorizationEndpoint().baseUri()
.
下面的清单显示了一个示例:
The following listing shows an example:
-
Java
-
Kotlin
-
Xml
@Configuration
@EnableWebSecurity
public class OAuth2LoginSecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.oauth2Login(oauth2 -> oauth2
.loginPage("/login/oauth2")
...
.authorizationEndpoint(authorization -> authorization
.baseUri("/login/oauth2/authorization")
...
)
);
return http.build();
}
}
@Configuration
@EnableWebSecurity
class OAuth2LoginSecurityConfig {
@Bean
open fun filterChain(http: HttpSecurity): SecurityFilterChain {
http {
oauth2Login {
loginPage = "/login/oauth2"
authorizationEndpoint {
baseUri = "/login/oauth2/authorization"
}
}
}
return http.build()
}
}
<http>
<oauth2-login login-page="/login/oauth2"
...
/>
</http>
您需要提供一个 @Controller
及其 @RequestMapping("/login/oauth2")
,能够呈现自定义登录页面。
You need to provide a @Controller
with a @RequestMapping("/login/oauth2")
that is capable of rendering the custom login page.
如前所述,配置 As noted earlier, configuring 以下行为示例: The following line shows an example:
|
Redirection Endpoint
授权服务器使用重定向端点来通过资源所有者的用户代理将授权响应(其中包含授权凭证)返回到客户端。
The Redirection Endpoint is used by the Authorization Server for returning the Authorization Response (which contains the authorization credentials) to the client through the Resource Owner user-agent.
OAuth 2.0 登录利用授权代码授予。因此,授权凭证就是授权代码。 OAuth 2.0 Login leverages the Authorization Code Grant. Therefore, the authorization credential is the authorization code. |
默认授权响应 baseUri
(重定向端点)是 /login/oauth2/code/*
,在 OAuth2LoginAuthenticationFilter.DEFAULT_FILTER_PROCESSES_URI
中定义。
The default Authorization Response baseUri
(redirection endpoint) is /login/oauth2/code/*
, which is defined in OAuth2LoginAuthenticationFilter.DEFAULT_FILTER_PROCESSES_URI
.
如果您要自定义授权响应 baseUri
,请按以下方式进行配置:
If you would like to customize the Authorization Response baseUri
, configure it as follows:
-
Java
-
Kotlin
-
Xml
@Configuration
@EnableWebSecurity
public class OAuth2LoginSecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.oauth2Login(oauth2 -> oauth2
.redirectionEndpoint(redirection -> redirection
.baseUri("/login/oauth2/callback/*")
...
)
);
return http.build();
}
}
@Configuration
@EnableWebSecurity
class OAuth2LoginSecurityConfig {
@Bean
open fun filterChain(http: HttpSecurity): SecurityFilterChain {
http {
oauth2Login {
redirectionEndpoint {
baseUri = "/login/oauth2/callback/*"
}
}
}
return http.build()
}
}
<http>
<oauth2-login login-processing-url="/login/oauth2/callback/*"
...
/>
</http>
您还需要确保 ClientRegistration.redirectUri
与自定义授权响应 baseUri
相匹配。
You also need to ensure the ClientRegistration.redirectUri
matches the custom Authorization Response baseUri
.
下面的清单显示了一个示例:
The following listing shows an example:
- Java
-
return CommonOAuth2Provider.GOOGLE.getBuilder("google") .clientId("google-client-id") .clientSecret("google-client-secret") .redirectUri("{baseUrl}/login/oauth2/callback/{registrationId}") .build();
- Kotlin
-
return CommonOAuth2Provider.GOOGLE.getBuilder("google") .clientId("google-client-id") .clientSecret("google-client-secret") .redirectUri("{baseUrl}/login/oauth2/callback/{registrationId}") .build()
UserInfo Endpoint
UserInfo 终结点包括多个配置选项,如下小节所述:
The UserInfo Endpoint includes a number of configuration options, as described in the following sub-sections:
Mapping User Authorities
在用户成功通过 OAuth 2.0 提供程序进行身份验证之后,OAuth2User.getAuthorities()
(或 OidcUser.getAuthorities()
)将包含一个权限列表,该列表从 OAuth2UserRequest.getAccessToken().getScopes()
中填充并以 SCOPE_
作为前缀。这些被授予的权限可以映射到一组新的 GrantedAuthority
实例,在完成身份验证时提供给 OAuth2AuthenticationToken
。
After the user successfully authenticates with the OAuth 2.0 Provider, the OAuth2User.getAuthorities()
(or OidcUser.getAuthorities()
) contains a list of granted authorities populated from OAuth2UserRequest.getAccessToken().getScopes()
and prefixed with SCOPE_
.
These granted authorities can be mapped to a new set of GrantedAuthority
instances, which are supplied to OAuth2AuthenticationToken
when completing the authentication.
|
|
在映射用户权限时有几个选项可供选择:
There are a couple of options to choose from when mapping user authorities:
Using a GrantedAuthoritiesMapper
GrantedAuthoritiesMapper
具有被授予的权限列表,其中包含 OAuth2UserAuthority
类型和权限字符串 OAUTH2_USER
(或 OidcUserAuthority
和权限字符串 OIDC_USER
)的特殊权限。
The GrantedAuthoritiesMapper
is given a list of granted authorities which contains a special authority of type OAuth2UserAuthority
and the authority string OAUTH2_USER
(or OidcUserAuthority
and the authority string OIDC_USER
).
提供 GrantedAuthoritiesMapper
的实现并进行以下配置:
Provide an implementation of GrantedAuthoritiesMapper
and configure it, as follows:
-
Java
-
Kotlin
-
Xml
@Configuration
@EnableWebSecurity
public class OAuth2LoginSecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.oauth2Login(oauth2 -> oauth2
.userInfoEndpoint(userInfo -> userInfo
.userAuthoritiesMapper(this.userAuthoritiesMapper())
...
)
);
return http.build();
}
private GrantedAuthoritiesMapper userAuthoritiesMapper() {
return (authorities) -> {
Set<GrantedAuthority> mappedAuthorities = new HashSet<>();
authorities.forEach(authority -> {
if (OidcUserAuthority.class.isInstance(authority)) {
OidcUserAuthority oidcUserAuthority = (OidcUserAuthority)authority;
OidcIdToken idToken = oidcUserAuthority.getIdToken();
OidcUserInfo userInfo = oidcUserAuthority.getUserInfo();
// Map the claims found in idToken and/or userInfo
// to one or more GrantedAuthority's and add it to mappedAuthorities
} else if (OAuth2UserAuthority.class.isInstance(authority)) {
OAuth2UserAuthority oauth2UserAuthority = (OAuth2UserAuthority)authority;
Map<String, Object> userAttributes = oauth2UserAuthority.getAttributes();
// Map the attributes found in userAttributes
// to one or more GrantedAuthority's and add it to mappedAuthorities
}
});
return mappedAuthorities;
};
}
}
@Configuration
@EnableWebSecurity
class OAuth2LoginSecurityConfig {
@Bean
open fun filterChain(http: HttpSecurity): SecurityFilterChain {
http {
oauth2Login {
userInfoEndpoint {
userAuthoritiesMapper = userAuthoritiesMapper()
}
}
}
return http.build()
}
private fun userAuthoritiesMapper(): GrantedAuthoritiesMapper = GrantedAuthoritiesMapper { authorities: Collection<GrantedAuthority> ->
val mappedAuthorities = emptySet<GrantedAuthority>()
authorities.forEach { authority ->
if (authority is OidcUserAuthority) {
val idToken = authority.idToken
val userInfo = authority.userInfo
// Map the claims found in idToken and/or userInfo
// to one or more GrantedAuthority's and add it to mappedAuthorities
} else if (authority is OAuth2UserAuthority) {
val userAttributes = authority.attributes
// Map the attributes found in userAttributes
// to one or more GrantedAuthority's and add it to mappedAuthorities
}
}
mappedAuthorities
}
}
<http>
<oauth2-login user-authorities-mapper-ref="userAuthoritiesMapper"
...
/>
</http>
或者,您可以注册一个 GrantedAuthoritiesMapper
@Bean
,以自动将其应用到以下配置:
Alternatively, you can register a GrantedAuthoritiesMapper
@Bean
to have it automatically applied to the configuration, as follows:
-
Java
-
Kotlin
@Configuration
@EnableWebSecurity
public class OAuth2LoginSecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.oauth2Login(withDefaults());
return http.build();
}
@Bean
public GrantedAuthoritiesMapper userAuthoritiesMapper() {
...
}
}
@Configuration
@EnableWebSecurity
class OAuth2LoginSecurityConfig {
@Bean
open fun filterChain(http: HttpSecurity): SecurityFilterChain {
http {
oauth2Login { }
}
return http.build()
}
@Bean
fun userAuthoritiesMapper(): GrantedAuthoritiesMapper {
...
}
}
Delegation-based Strategy with OAuth2UserService
与使用 GrantedAuthoritiesMapper
相比,此策略是高级的。然而,它也更灵活,因为它可以访问 OAuth2UserRequest
和 OAuth2User
(在使用 OAuth 2.0 UserService 时)或 OidcUserRequest
和 OidcUser
(在使用 OpenID Connect 1.0 UserService 时)。
This strategy is advanced compared to using a GrantedAuthoritiesMapper
. However, it is also more flexible, as it gives you access to the OAuth2UserRequest
and OAuth2User
(when using an OAuth 2.0 UserService) or OidcUserRequest
and OidcUser
(when using an OpenID Connect 1.0 UserService).
OAuth2UserRequest
(和 OidcUserRequest
)可让您访问关联的 OAuth2AccessToken
,在 delegator 需要从受保护的资源中获取权限信息才能映射用户的自定义权限的情况下,这是一个非常有用的功能。
The OAuth2UserRequest
(and OidcUserRequest
) provides you access to the associated OAuth2AccessToken
, which is very useful in cases where the delegator needs to fetch authority information from a protected resource before it can map the custom authorities for the user.
以下示例展示了如何使用 OpenID Connect 1.0 UserService 实现和配置基于委派的策略:
The following example shows how to implement and configure a delegation-based strategy using an OpenID Connect 1.0 UserService:
-
Java
-
Kotlin
-
Xml
@Configuration
@EnableWebSecurity
public class OAuth2LoginSecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.oauth2Login(oauth2 -> oauth2
.userInfoEndpoint(userInfo -> userInfo
.oidcUserService(this.oidcUserService())
...
)
);
return http.build();
}
private OAuth2UserService<OidcUserRequest, OidcUser> oidcUserService() {
final OidcUserService delegate = new OidcUserService();
return (userRequest) -> {
// Delegate to the default implementation for loading a user
OidcUser oidcUser = delegate.loadUser(userRequest);
OAuth2AccessToken accessToken = userRequest.getAccessToken();
Set<GrantedAuthority> mappedAuthorities = new HashSet<>();
// TODO
// 1) Fetch the authority information from the protected resource using accessToken
// 2) Map the authority information to one or more GrantedAuthority's and add it to mappedAuthorities
// 3) Create a copy of oidcUser but use the mappedAuthorities instead
ProviderDetails providerDetails = userRequest.getClientRegistration().getProviderDetails();
String userNameAttributeName = providerDetails.getUserInfoEndpoint().getUserNameAttributeName();
if (StringUtils.hasText(userNameAttributeName)) {
oidcUser = new DefaultOidcUser(mappedAuthorities, oidcUser.getIdToken(), oidcUser.getUserInfo(), userNameAttributeName);
} else {
oidcUser = new DefaultOidcUser(mappedAuthorities, oidcUser.getIdToken(), oidcUser.getUserInfo());
}
return oidcUser;
};
}
}
@Configuration
@EnableWebSecurity
class OAuth2LoginSecurityConfig {
@Bean
open fun filterChain(http: HttpSecurity): SecurityFilterChain {
http {
oauth2Login {
userInfoEndpoint {
oidcUserService = oidcUserService()
}
}
}
return http.build()
}
@Bean
fun oidcUserService(): OAuth2UserService<OidcUserRequest, OidcUser> {
val delegate = OidcUserService()
return OAuth2UserService { userRequest ->
// Delegate to the default implementation for loading a user
val oidcUser = delegate.loadUser(userRequest)
val accessToken = userRequest.accessToken
val mappedAuthorities = HashSet<GrantedAuthority>()
// TODO
// 1) Fetch the authority information from the protected resource using accessToken
// 2) Map the authority information to one or more GrantedAuthority's and add it to mappedAuthorities
// 3) Create a copy of oidcUser but use the mappedAuthorities instead
val providerDetails = userRequest.getClientRegistration().getProviderDetails()
val userNameAttributeName = providerDetails.getUserInfoEndpoint().getUserNameAttributeName()
if (StringUtils.hasText(userNameAttributeName)) {
DefaultOidcUser(mappedAuthorities, oidcUser.idToken, oidcUser.userInfo, userNameAttributeName)
} else {
DefaultOidcUser(mappedAuthorities, oidcUser.idToken, oidcUser.userInfo)
}
}
}
}
<http>
<oauth2-login oidc-user-service-ref="oidcUserService"
...
/>
</http>
OAuth 2.0 UserService
DefaultOAuth2UserService
是 OAuth2UserService
的一个实现,它支持标准 OAuth 2.0 提供商。
DefaultOAuth2UserService
is an implementation of an OAuth2UserService
that supports standard OAuth 2.0 Provider’s.
|
DefaultOAuth2UserService
在 UserInfo 端点请求用户属性时,使用 RestOperations
实例。
DefaultOAuth2UserService
uses a RestOperations
instance when requesting the user attributes at the UserInfo Endpoint.
如果你需要自定义 UserInfo Request 的预处理,则可以为 DefaultOAuth2UserService.setRequestEntityConverter()
提供自定义 Converter<OAuth2UserRequest, RequestEntity<?>>
。默认实现 OAuth2UserRequestEntityConverter
构建了一个 UserInfo Request 的 RequestEntity
表示形式,默认情况下,在 Authorization
标头中设置 OAuth2AccessToken
。
If you need to customize the pre-processing of the UserInfo Request, you can provide DefaultOAuth2UserService.setRequestEntityConverter()
with a custom Converter<OAuth2UserRequest, RequestEntity<?>>
.
The default implementation OAuth2UserRequestEntityConverter
builds a RequestEntity
representation of a UserInfo Request that sets the OAuth2AccessToken
in the Authorization
header by default.
另一方面,如果你需要自定义 UserInfo Response 的后处理,则需要为 DefaultOAuth2UserService.setRestOperations()
提供自定义配置的 RestOperations
。默认 RestOperations
配置如下:
On the other end, if you need to customize the post-handling of the UserInfo Response, you need to provide DefaultOAuth2UserService.setRestOperations()
with a custom configured RestOperations
.
The default RestOperations
is configured as follows:
RestTemplate restTemplate = new RestTemplate();
restTemplate.setErrorHandler(new OAuth2ErrorResponseErrorHandler());
OAuth2ErrorResponseErrorHandler
是 ResponseErrorHandler
,它可以处理 OAuth 2.0 错误(400 Bad Request)。它使用 OAuth2ErrorHttpMessageConverter
将 OAuth 2.0 错误参数转换为 OAuth2Error
。
OAuth2ErrorResponseErrorHandler
is a ResponseErrorHandler
that can handle an OAuth 2.0 Error (400 Bad Request).
It uses an OAuth2ErrorHttpMessageConverter
for converting the OAuth 2.0 Error parameters to an OAuth2Error
.
无论你自定义 DefaultOAuth2UserService
还是提供自己的 OAuth2UserService
实现,你都需要按照如下方式配置它:
Whether you customize DefaultOAuth2UserService
or provide your own implementation of OAuth2UserService
, you need to configure it as follows:
-
Java
-
Kotlin
@Configuration
@EnableWebSecurity
public class OAuth2LoginSecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.oauth2Login(oauth2 -> oauth2
.userInfoEndpoint(userInfo -> userInfo
.userService(this.oauth2UserService())
...
)
);
return http.build();
}
private OAuth2UserService<OAuth2UserRequest, OAuth2User> oauth2UserService() {
...
}
}
@Configuration
@EnableWebSecurity
class OAuth2LoginSecurityConfig {
@Bean
open fun filterChain(http: HttpSecurity): SecurityFilterChain {
http {
oauth2Login {
userInfoEndpoint {
userService = oauth2UserService()
// ...
}
}
}
return http.build()
}
private fun oauth2UserService(): OAuth2UserService<OAuth2UserRequest, OAuth2User> {
// ...
}
}
OpenID Connect 1.0 UserService
OidcUserService
是 OAuth2UserService
的一个实现,它支持 OpenID Connect 1.0 提供商。
OidcUserService
is an implementation of an OAuth2UserService
that supports OpenID Connect 1.0 Provider’s.
OidcUserService
在 UserInfo 端点请求用户属性时利用 DefaultOAuth2UserService
。
The OidcUserService
leverages the DefaultOAuth2UserService
when requesting the user attributes at the UserInfo Endpoint.
如果你需要自定义 UserInfo Request 的预处理或 UserInfo Response 的后处理,则需要为 OidcUserService.setOauth2UserService()
提供自定义配置的 DefaultOAuth2UserService
。
If you need to customize the pre-processing of the UserInfo Request or the post-handling of the UserInfo Response, you need to provide OidcUserService.setOauth2UserService()
with a custom configured DefaultOAuth2UserService
.
无论你自定义 OidcUserService
还是为 OpenID Connect 1.0 提供商提供 OAuth2UserService
自己的实现,你都需要按照如下方式配置它:
Whether you customize OidcUserService
or provide your own implementation of OAuth2UserService
for OpenID Connect 1.0 Provider’s, you need to configure it as follows:
-
Java
-
Kotlin
@Configuration
@EnableWebSecurity
public class OAuth2LoginSecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.oauth2Login(oauth2 -> oauth2
.userInfoEndpoint(userInfo -> userInfo
.oidcUserService(this.oidcUserService())
...
)
);
return http.build();
}
private OAuth2UserService<OidcUserRequest, OidcUser> oidcUserService() {
...
}
}
@Configuration
@EnableWebSecurity
class OAuth2LoginSecurityConfig {
@Bean
open fun filterChain(http: HttpSecurity): SecurityFilterChain {
http {
oauth2Login {
userInfoEndpoint {
oidcUserService = oidcUserService()
// ...
}
}
}
return http.build()
}
private fun oidcUserService(): OAuth2UserService<OidcUserRequest, OidcUser> {
// ...
}
}
ID Token Signature Verification
OpenID Connect 1.0 Authentication introduces the ID Token, which is a security token that contains Claims about the Authentication of an End-User by an Authorization Server when used by a Client.
ID 令牌表示为 JSON Web Token (JWT),必须使用 JSON Web Signature (JWS) 进行签名。
The ID Token is represented as a JSON Web Token (JWT) and MUST be signed by using JSON Web Signature (JWS).
OidcIdTokenDecoderFactory
提供 JwtDecoder
,用于 OidcIdToken
签名验证。默认算法为 RS256
,但在客户端注册期间分配时可能有所不同。对于这些情况,你可以配置解析器以返回为特定客户端分配的预期 JWS 算法。
The OidcIdTokenDecoderFactory
provides a JwtDecoder
used for OidcIdToken
signature verification. The default algorithm is RS256
but may be different when assigned during client registration.
For these cases, you can configure a resolver to return the expected JWS algorithm assigned for a specific client.
JWS 算法解析器是 Function
,它接受 ClientRegistration
并为客户端返回预期的 JwsAlgorithm
,例如 SignatureAlgorithm.RS256
或 MacAlgorithm.HS256
。
The JWS algorithm resolver is a Function
that accepts a ClientRegistration
and returns the expected JwsAlgorithm
for the client, such as SignatureAlgorithm.RS256
or MacAlgorithm.HS256
以下代码展示了如何配置 OidcIdTokenDecoderFactory
@Bean
,使其对于所有 ClientRegistration
实例默认为 MacAlgorithm.HS256
:
The following code shows how to configure the OidcIdTokenDecoderFactory
@Bean
to default to MacAlgorithm.HS256
for all ClientRegistration
instances:
-
Java
-
Kotlin
@Bean
public JwtDecoderFactory<ClientRegistration> idTokenDecoderFactory() {
OidcIdTokenDecoderFactory idTokenDecoderFactory = new OidcIdTokenDecoderFactory();
idTokenDecoderFactory.setJwsAlgorithmResolver(clientRegistration -> MacAlgorithm.HS256);
return idTokenDecoderFactory;
}
@Bean
fun idTokenDecoderFactory(): JwtDecoderFactory<ClientRegistration?> {
val idTokenDecoderFactory = OidcIdTokenDecoderFactory()
idTokenDecoderFactory.setJwsAlgorithmResolver { MacAlgorithm.HS256 }
return idTokenDecoderFactory
}
对于基于 MAC 的算法(例如 For MAC-based algorithms (such as |
如果为 OpenID Connect 1.0 身份验证配置了多个 If more than one |
然后,你可以继续配置logout
Then, you can proceed to configure logout