Core Interfaces / Classes
ClientRegistration
OAuth2AccessToken
是向 OAuth 2.0 或 OpenID Connect 1.0 提供程序注册的客户端的表示形式。
ClientRegistration
is a representation of a client registered with an OAuth 2.0 or OpenID Connect 1.0 Provider.
客户端注册保存了信息,例如客户端 ID、客户端机密、授权授予类型、重定向 URI、范围、授权 URI、令牌 URI 和其他详细信息。
A client registration holds information, such as client id, client secret, authorization grant type, redirect URI, scope(s), authorization URI, token URI, and other details.
ClientRegistration
及其属性被定义如下:
ClientRegistration
and its properties are defined as follows:
public final class ClientRegistration {
private String registrationId; 1
private String clientId; 2
private String clientSecret; 3
private ClientAuthenticationMethod clientAuthenticationMethod; 4
private AuthorizationGrantType authorizationGrantType; 5
private String redirectUri; 6
private Set<String> scopes; 7
private ProviderDetails providerDetails;
private String clientName; 8
public class ProviderDetails {
private String authorizationUri; 9
private String tokenUri; 10
private UserInfoEndpoint userInfoEndpoint;
private String jwkSetUri; 11
private String issuerUri; 12
private Map<String, Object> configurationMetadata; 13
public class UserInfoEndpoint {
private String uri; 14
private AuthenticationMethod authenticationMethod; 15
private String userNameAttributeName; 16
}
}
}
1 | registrationId : The ID that uniquely identifies the ClientRegistration . |
2 | clientId : The client identifier. |
3 | clientSecret : The client secret. |
4 | clientAuthenticationMethod : The method used to authenticate the Client with the Provider.
The supported values are client_secret_basic, client_secret_post, private_key_jwt, client_secret_jwt and none (public clients). |
5 | authorizationGrantType : The OAuth 2.0 Authorization Framework defines four Authorization Grant types.
The supported values are authorization_code , client_credentials , password , as well as, extension grant type urn:ietf:params:oauth:grant-type:jwt-bearer . |
6 | redirectUri : The client’s registered redirect URI that the Authorization Server redirects the end-user’s user-agent
to after the end-user has authenticated and authorized access to the client. |
7 | scopes : The scope(s) requested by the client during the Authorization Request flow, such as openid, email, or profile. |
8 | clientName : A descriptive name used for the client.
The name may be used in certain scenarios, such as when displaying the name of the client in the auto-generated login page. |
9 | authorizationUri : The Authorization Endpoint URI for the Authorization Server. |
10 | tokenUri : The Token Endpoint URI for the Authorization Server. |
11 | jwkSetUri : The URI used to retrieve the JSON Web Key (JWK) Set from the Authorization Server,
which contains the cryptographic key(s) used to verify the JSON Web Signature (JWS) of the ID Token and optionally the UserInfo Response. |
12 | issuerUri : Returns the issuer identifier uri for the OpenID Connect 1.0 provider or the OAuth 2.0 Authorization Server. |
13 | configurationMetadata : The OpenID Provider Configuration Information.
This information will only be available if the Spring Boot 2.x property spring.security.oauth2.client.provider.[providerId].issuerUri is configured. |
14 | (userInfoEndpoint)uri : The UserInfo Endpoint URI used to access the claims/attributes of the authenticated end-user. |
15 | (userInfoEndpoint)authenticationMethod : The authentication method used when sending the access token to the UserInfo Endpoint.
The supported values are header, form and query. |
16 | userNameAttributeName : The name of the attribute returned in the UserInfo Response that references the Name or Identifier of the end-user. |
可以使用 OpenID Connect 提供程序的 Configuration endpoint或授权服务器的 Metadata endpoint的发现来最初配置 ClientRegistration
。
A ClientRegistration
can be initially configured using discovery of an OpenID Connect Provider’s Configuration endpoint or an Authorization Server’s Metadata endpoint.
ClientRegistrations
提供了通过这种方式配置 ClientRegistration
的便捷方法,如以下示例所示:
ClientRegistrations
provides convenience methods for configuring a ClientRegistration
in this way, as can be seen in the following example:
-
Java
-
Kotlin
ClientRegistration clientRegistration =
ClientRegistrations.fromIssuerLocation("https://idp.example.com/issuer").build();
val clientRegistration = ClientRegistrations.fromIssuerLocation("https://idp.example.com/issuer").build()
以上代码将按顺序查询 https://idp.example.com/issuer/.well-known/openid-configuration
、然后是 https://idp.example.com/.well-known/openid-configuration/issuer
,最后是 https://idp.example.com/.well-known/oauth-authorization-server/issuer
,然后在第一个返回 200 响应时停止。
The above code will query in series https://idp.example.com/issuer/.well-known/openid-configuration
, and then https://idp.example.com/.well-known/openid-configuration/issuer
, and finally https://idp.example.com/.well-known/oauth-authorization-server/issuer
, stopping at the first to return a 200 response.
或者,您可以使用 ClientRegistrations.fromOidcIssuerLocation()
仅查询 OpenID Connect 提供者的配置端点。
As an alternative, you can use ClientRegistrations.fromOidcIssuerLocation()
to only query the OpenID Connect Provider’s Configuration endpoint.
ReactiveClientRegistrationRepository
ReactiveClientRegistrationRepository
用作 OAuth 2.0/OpenID Connect 1.0 ClientRegistration
的存储库。
The ReactiveClientRegistrationRepository
serves as a repository for OAuth 2.0 / OpenID Connect 1.0 ClientRegistration
(s).
客户端注册信息最终由相关的授权服务器存储和拥有。该存储库提供检索一组主客户端注册信息的功能,该信息与授权服务器一起存储。 |
Client registration information is ultimately stored and owned by the associated Authorization Server. This repository provides the ability to retrieve a sub-set of the primary client registration information, which is stored with the Authorization Server. |
Spring Boot 2.x 自动配置将 `spring.security.oauth2.client.registration.[registrationId]`下每个属性绑定到 `ClientRegistration`的一个实例,然后在 `ReactiveClientRegistrationRepository`中组合每个 `ClientRegistration`实例。
Spring Boot 2.x auto-configuration binds each of the properties under spring.security.oauth2.client.registration.[registrationId]
to an instance of ClientRegistration
and then composes each of the ClientRegistration
instance(s) within a ReactiveClientRegistrationRepository
.
|
The default implementation of |
自动配置还将 ReactiveClientRegistrationRepository
注册为 ApplicationContext
中的 @Bean
,以便在应用程序需要时可以使用依赖注入。
The auto-configuration also registers the ReactiveClientRegistrationRepository
as a @Bean
in the ApplicationContext
so that it is available for dependency-injection, if needed by the application.
下面的清单显示了一个示例:
The following listing shows an example:
-
Java
-
Kotlin
@Controller
public class OAuth2ClientController {
@Autowired
private ReactiveClientRegistrationRepository clientRegistrationRepository;
@GetMapping("/")
public Mono<String> index() {
return this.clientRegistrationRepository.findByRegistrationId("okta")
...
.thenReturn("index");
}
}
@Controller
class OAuth2ClientController {
@Autowired
private lateinit var clientRegistrationRepository: ReactiveClientRegistrationRepository
@GetMapping("/")
fun index(): Mono<String> {
return this.clientRegistrationRepository.findByRegistrationId("okta")
...
.thenReturn("index")
}
}
OAuth2AuthorizedClient
OAuth2AuthorizedClient
是授权客户端的一个表示。当最终用户(资源所有者)授予客户端访问其受保护资源的授权时,客户端被认为是已授权的。
OAuth2AuthorizedClient
is a representation of an Authorized Client.
A client is considered to be authorized when the end-user (Resource Owner) has granted authorization to the client to access its protected resources.
OAuth2AuthorizedClient
的作用是将 OAuth2AccessToken
(和可选的 OAuth2RefreshToken
)关联到 ClientRegistration
(客户端)和资源所有者(即授予授权的 Principal
最终用户)。
OAuth2AuthorizedClient
serves the purpose of associating an OAuth2AccessToken
(and optional OAuth2RefreshToken
) to a ClientRegistration
(client) and resource owner, who is the Principal
end-user that granted the authorization.
ServerOAuth2AuthorizedClientRepository / ReactiveOAuth2AuthorizedClientService
ServerOAuth2AuthorizedClientRepository
负责在 Web 请求之间保留 OAuth2AuthorizedClient
。相对而言,ReactiveOAuth2AuthorizedClientService
的主要角色是管理应用程序级别的 OAuth2AuthorizedClient
。
ServerOAuth2AuthorizedClientRepository
is responsible for persisting OAuth2AuthorizedClient
(s) between web requests.
Whereas, the primary role of ReactiveOAuth2AuthorizedClientService
is to manage OAuth2AuthorizedClient
(s) at the application-level.
从开发者的角度来看,ServerOAuth2AuthorizedClientRepository
或 ReactiveOAuth2AuthorizedClientService
提供了查找与一个客户端相关联的 OAuth2AccessToken
的能力,以便可以将其用于发起受保护的资源请求。
From a developer perspective, the ServerOAuth2AuthorizedClientRepository
or ReactiveOAuth2AuthorizedClientService
provides the capability to lookup an OAuth2AccessToken
associated with a client so that it may be used to initiate a protected resource request.
下面的清单显示了一个示例:
The following listing shows an example:
-
Java
-
Kotlin
@Controller
public class OAuth2ClientController {
@Autowired
private ReactiveOAuth2AuthorizedClientService authorizedClientService;
@GetMapping("/")
public Mono<String> index(Authentication authentication) {
return this.authorizedClientService.loadAuthorizedClient("okta", authentication.getName())
.map(OAuth2AuthorizedClient::getAccessToken)
...
.thenReturn("index");
}
}
@Controller
class OAuth2ClientController {
@Autowired
private lateinit var authorizedClientService: ReactiveOAuth2AuthorizedClientService
@GetMapping("/")
fun index(authentication: Authentication): Mono<String> {
return this.authorizedClientService.loadAuthorizedClient<OAuth2AuthorizedClient>("okta", authentication.name)
.map { it.accessToken }
...
.thenReturn("index")
}
}
Spring Boot 2.x 自动配置在 |
Spring Boot 2.x auto-configuration registers an |
ReactiveOAuth2AuthorizedClientService
的默认实现为 InMemoryReactiveOAuth2AuthorizedClientService
,它在内存中储存 OAuth2AuthorizedClient
。
The default implementation of ReactiveOAuth2AuthorizedClientService
is InMemoryReactiveOAuth2AuthorizedClientService
, which stores OAuth2AuthorizedClient
(s) in-memory.
另外地,R2DBC 实现 R2dbcReactiveOAuth2AuthorizedClientService
还可以被配置为在一个数据库中保留 OAuth2AuthorizedClient
。
Alternatively, the R2DBC implementation R2dbcReactiveOAuth2AuthorizedClientService
may be configured for persisting OAuth2AuthorizedClient
(s) in a database.
|
|
ReactiveOAuth2AuthorizedClientManager / ReactiveOAuth2AuthorizedClientProvider
ReactiveOAuth2AuthorizedClientManager
负责 OAuth2AuthorizedClient
的整体管理。
The ReactiveOAuth2AuthorizedClientManager
is responsible for the overall management of OAuth2AuthorizedClient
(s).
主要职责包括:
The primary responsibilities include:
-
Authorizing (or re-authorizing) an OAuth 2.0 Client, using a
ReactiveOAuth2AuthorizedClientProvider
. -
Delegating the persistence of an
OAuth2AuthorizedClient
, typically using aReactiveOAuth2AuthorizedClientService
orServerOAuth2AuthorizedClientRepository
. -
Delegating to a
ReactiveOAuth2AuthorizationSuccessHandler
when an OAuth 2.0 Client has been successfully authorized (or re-authorized). -
Delegating to a
ReactiveOAuth2AuthorizationFailureHandler
when an OAuth 2.0 Client fails to authorize (or re-authorize).
一个 ReactiveOAuth2AuthorizedClientProvider
实现了了一个授权(或重新授权) OAuth 2.0 客户端的策略。这些实现通常会实现一个授权许可类型,例如 authorization_code
、client_credentials
等。
A ReactiveOAuth2AuthorizedClientProvider
implements a strategy for authorizing (or re-authorizing) an OAuth 2.0 Client.
Implementations will typically implement an authorization grant type, eg. authorization_code
, client_credentials
, etc.
ReactiveOAuth2AuthorizedClientManager
的默认实现为 DefaultReactiveOAuth2AuthorizedClientManager
,它与一个 ReactiveOAuth2AuthorizedClientProvider
关联在一起,该 ReactiveOAuth2AuthorizedClientProvider
可能支持多个授权许可类型,使用基于委托的组合。ReactiveOAuth2AuthorizedClientProviderBuilder
可以在配置和构建基于委托的组合时使用。
The default implementation of ReactiveOAuth2AuthorizedClientManager
is DefaultReactiveOAuth2AuthorizedClientManager
, which is associated with a ReactiveOAuth2AuthorizedClientProvider
that may support multiple authorization grant types using a delegation-based composite.
The ReactiveOAuth2AuthorizedClientProviderBuilder
may be used to configure and build the delegation-based composite.
下面的代码展示了一个如何配置和构建一个 ReactiveOAuth2AuthorizedClientProvider
组合的示例,该组合为 authorization_code
、refresh_token
、client_credentials
和 password
授权许可类型提供支持:
The following code shows an example of how to configure and build a ReactiveOAuth2AuthorizedClientProvider
composite that provides support for the authorization_code
, refresh_token
, client_credentials
and password
authorization grant types:
-
Java
-
Kotlin
@Bean
public ReactiveOAuth2AuthorizedClientManager authorizedClientManager(
ReactiveClientRegistrationRepository clientRegistrationRepository,
ServerOAuth2AuthorizedClientRepository authorizedClientRepository) {
ReactiveOAuth2AuthorizedClientProvider authorizedClientProvider =
ReactiveOAuth2AuthorizedClientProviderBuilder.builder()
.authorizationCode()
.refreshToken()
.clientCredentials()
.password()
.build();
DefaultReactiveOAuth2AuthorizedClientManager authorizedClientManager =
new DefaultReactiveOAuth2AuthorizedClientManager(
clientRegistrationRepository, authorizedClientRepository);
authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider);
return authorizedClientManager;
}
@Bean
fun authorizedClientManager(
clientRegistrationRepository: ReactiveClientRegistrationRepository,
authorizedClientRepository: ServerOAuth2AuthorizedClientRepository): ReactiveOAuth2AuthorizedClientManager {
val authorizedClientProvider: ReactiveOAuth2AuthorizedClientProvider = ReactiveOAuth2AuthorizedClientProviderBuilder.builder()
.authorizationCode()
.refreshToken()
.clientCredentials()
.password()
.build()
val authorizedClientManager = DefaultReactiveOAuth2AuthorizedClientManager(
clientRegistrationRepository, authorizedClientRepository)
authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider)
return authorizedClientManager
}
当一个授权尝试成功时,DefaultReactiveOAuth2AuthorizedClientManager
会委托给 ReactiveOAuth2AuthorizationSuccessHandler
,后者(默认情况下)会通过 ServerOAuth2AuthorizedClientRepository
保存 OAuth2AuthorizedClient
。如果重新授权失败,例如刷新令牌不再有效,则先前保存的 OAuth2AuthorizedClient
会通过 RemoveAuthorizedClientReactiveOAuth2AuthorizationFailureHandler
从 ServerOAuth2AuthorizedClientRepository
中删除。可以用 setAuthorizationSuccessHandler(ReactiveOAuth2AuthorizationSuccessHandler)
和 setAuthorizationFailureHandler(ReactiveOAuth2AuthorizationFailureHandler)
自定义默认行为。
When an authorization attempt succeeds, the DefaultReactiveOAuth2AuthorizedClientManager
will delegate to the ReactiveOAuth2AuthorizationSuccessHandler
, which (by default) will save the OAuth2AuthorizedClient
via the ServerOAuth2AuthorizedClientRepository
.
In the case of a re-authorization failure, eg. a refresh token is no longer valid, the previously saved OAuth2AuthorizedClient
will be removed from the ServerOAuth2AuthorizedClientRepository
via the RemoveAuthorizedClientReactiveOAuth2AuthorizationFailureHandler
.
The default behaviour may be customized via setAuthorizationSuccessHandler(ReactiveOAuth2AuthorizationSuccessHandler)
and setAuthorizationFailureHandler(ReactiveOAuth2AuthorizationFailureHandler)
.
DefaultReactiveOAuth2AuthorizedClientManager
也与一个类型为 Function<OAuth2AuthorizeRequest, Mono<Map<String, Object>>>
的 contextAttributesMapper
关联,该 contextAttributesMapper
负责将属性从 OAuth2AuthorizeRequest
映射到一个属性 Map
,该属性将与 OAuth2AuthorizationContext
关联。当您需要向 ReactiveOAuth2AuthorizedClientProvider
提供所需(支持的)属性时,这会很有用,例如 PasswordReactiveOAuth2AuthorizedClientProvider
要求资源所有者的 username
和 password
在 OAuth2AuthorizationContext.getAttributes()
中可用。
The DefaultReactiveOAuth2AuthorizedClientManager
is also associated with a contextAttributesMapper
of type Function<OAuth2AuthorizeRequest, Mono<Map<String, Object>>>
, which is responsible for mapping attribute(s) from the OAuth2AuthorizeRequest
to a Map
of attributes to be associated to the OAuth2AuthorizationContext
.
This can be useful when you need to supply a ReactiveOAuth2AuthorizedClientProvider
with required (supported) attribute(s), eg. the PasswordReactiveOAuth2AuthorizedClientProvider
requires the resource owner’s username
and password
to be available in OAuth2AuthorizationContext.getAttributes()
.
以下代码显示了 contextAttributesMapper
的示例:
The following code shows an example of the contextAttributesMapper
:
-
Java
-
Kotlin
@Bean
public ReactiveOAuth2AuthorizedClientManager authorizedClientManager(
ReactiveClientRegistrationRepository clientRegistrationRepository,
ServerOAuth2AuthorizedClientRepository authorizedClientRepository) {
ReactiveOAuth2AuthorizedClientProvider authorizedClientProvider =
ReactiveOAuth2AuthorizedClientProviderBuilder.builder()
.password()
.refreshToken()
.build();
DefaultReactiveOAuth2AuthorizedClientManager authorizedClientManager =
new DefaultReactiveOAuth2AuthorizedClientManager(
clientRegistrationRepository, authorizedClientRepository);
authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider);
// Assuming the `username` and `password` are supplied as `ServerHttpRequest` parameters,
// map the `ServerHttpRequest` parameters to `OAuth2AuthorizationContext.getAttributes()`
authorizedClientManager.setContextAttributesMapper(contextAttributesMapper());
return authorizedClientManager;
}
private Function<OAuth2AuthorizeRequest, Mono<Map<String, Object>>> contextAttributesMapper() {
return authorizeRequest -> {
Map<String, Object> contextAttributes = Collections.emptyMap();
ServerWebExchange exchange = authorizeRequest.getAttribute(ServerWebExchange.class.getName());
ServerHttpRequest request = exchange.getRequest();
String username = request.getQueryParams().getFirst(OAuth2ParameterNames.USERNAME);
String password = request.getQueryParams().getFirst(OAuth2ParameterNames.PASSWORD);
if (StringUtils.hasText(username) && StringUtils.hasText(password)) {
contextAttributes = new HashMap<>();
// `PasswordReactiveOAuth2AuthorizedClientProvider` requires both attributes
contextAttributes.put(OAuth2AuthorizationContext.USERNAME_ATTRIBUTE_NAME, username);
contextAttributes.put(OAuth2AuthorizationContext.PASSWORD_ATTRIBUTE_NAME, password);
}
return Mono.just(contextAttributes);
};
}
@Bean
fun authorizedClientManager(
clientRegistrationRepository: ReactiveClientRegistrationRepository,
authorizedClientRepository: ServerOAuth2AuthorizedClientRepository): ReactiveOAuth2AuthorizedClientManager {
val authorizedClientProvider: ReactiveOAuth2AuthorizedClientProvider = ReactiveOAuth2AuthorizedClientProviderBuilder.builder()
.password()
.refreshToken()
.build()
val authorizedClientManager = DefaultReactiveOAuth2AuthorizedClientManager(
clientRegistrationRepository, authorizedClientRepository)
authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider)
// Assuming the `username` and `password` are supplied as `ServerHttpRequest` parameters,
// map the `ServerHttpRequest` parameters to `OAuth2AuthorizationContext.getAttributes()`
authorizedClientManager.setContextAttributesMapper(contextAttributesMapper())
return authorizedClientManager
}
private fun contextAttributesMapper(): Function<OAuth2AuthorizeRequest, Mono<MutableMap<String, Any>>> {
return Function { authorizeRequest ->
var contextAttributes: MutableMap<String, Any> = mutableMapOf()
val exchange: ServerWebExchange = authorizeRequest.getAttribute(ServerWebExchange::class.java.name)!!
val request: ServerHttpRequest = exchange.request
val username: String? = request.queryParams.getFirst(OAuth2ParameterNames.USERNAME)
val password: String? = request.queryParams.getFirst(OAuth2ParameterNames.PASSWORD)
if (StringUtils.hasText(username) && StringUtils.hasText(password)) {
contextAttributes = hashMapOf()
// `PasswordReactiveOAuth2AuthorizedClientProvider` requires both attributes
contextAttributes[OAuth2AuthorizationContext.USERNAME_ATTRIBUTE_NAME] = username!!
contextAttributes[OAuth2AuthorizationContext.PASSWORD_ATTRIBUTE_NAME] = password!!
}
Mono.just(contextAttributes)
}
}
DefaultReactiveOAuth2AuthorizedClientManager
旨在在 ServerWebExchange
的上下文中使用 within。当在 ServerWebExchange
上下文 outside 操作时,请改用 AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager
。
The DefaultReactiveOAuth2AuthorizedClientManager
is designed to be used within the context of a ServerWebExchange
.
When operating outside of a ServerWebExchange
context, use AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager
instead.
一个 service application 是何时使用 AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager
的常见使用案例。服务应用程序通常在后台运行,没有任何用户交互,并且通常在系统级帐户而不是用户帐户下运行。配置了 client_credentials
许可类型的 OAuth 2.0 客户端可以被视为一种服务应用程序。
A service application is a common use case for when to use an AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager
.
Service applications often run in the background, without any user interaction, and typically run under a system-level account instead of a user account.
An OAuth 2.0 Client configured with the client_credentials
grant type can be considered a type of service application.
下面的代码展示了一个如何配置一个为 client_credentials
许可类型提供支持的 AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager
的示例:
The following code shows an example of how to configure an AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager
that provides support for the client_credentials
grant type:
-
Java
-
Kotlin
@Bean
public ReactiveOAuth2AuthorizedClientManager authorizedClientManager(
ReactiveClientRegistrationRepository clientRegistrationRepository,
ReactiveOAuth2AuthorizedClientService authorizedClientService) {
ReactiveOAuth2AuthorizedClientProvider authorizedClientProvider =
ReactiveOAuth2AuthorizedClientProviderBuilder.builder()
.clientCredentials()
.build();
AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager authorizedClientManager =
new AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager(
clientRegistrationRepository, authorizedClientService);
authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider);
return authorizedClientManager;
}
@Bean
fun authorizedClientManager(
clientRegistrationRepository: ReactiveClientRegistrationRepository,
authorizedClientService: ReactiveOAuth2AuthorizedClientService): ReactiveOAuth2AuthorizedClientManager {
val authorizedClientProvider: ReactiveOAuth2AuthorizedClientProvider = ReactiveOAuth2AuthorizedClientProviderBuilder.builder()
.clientCredentials()
.build()
val authorizedClientManager = AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager(
clientRegistrationRepository, authorizedClientService)
authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider)
return authorizedClientManager
}