Authorization Grant Support
Spring Security 提供了对以下授权赠送类型的支持:
-
授权代码
-
密码
-
客户凭据
-
客户端断言
-
JWT 持有者
对于每种授权类型,都有一个专门的 OAuth2AuthorizedClientProvider
实现,负责处理授权过程的特定方面。
除了提供对授权赠送的支持之外,Spring Security 还提供了对以下内容的支持:
-
刷新访问令牌
-
自定义授权请求和响应
-
存储授权请求和响应
-
使用配置的
RestTemplate
配置授权代码令牌响应处理程序
此支持使开发人员能够轻松地将 OAuth 2.0 授权流程集成到他们的 Spring Boot 应用程序中。
本部分介绍 Spring Security 对授权赠送的支持。
This section describes Spring Security’s support for authorization grants.
Authorization Code
有关 Authorization Code 授权的更多详情,请参阅 OAuth 2.0 授权框架。 See the OAuth 2.0 Authorization Framework for further details on the Authorization Code grant. |
Obtaining Authorization
有关授权码授权,请参阅 Authorization Request/Response 协议流程。 See the Authorization Request/Response protocol flow for the Authorization Code grant. |
Initiating the Authorization Request
OAuth2AuthorizationRequestRedirectFilter
使用 OAuth2AuthorizationRequestResolver
来解析 OAuth2AuthorizationRequest
并通过将最终用户的用户代理重定向到授权服务器的授权端点,从而启动授权码授权流。
The OAuth2AuthorizationRequestRedirectFilter
uses an OAuth2AuthorizationRequestResolver
to resolve an OAuth2AuthorizationRequest
and initiate the Authorization Code grant flow by redirecting the end-user’s user-agent to the Authorization Server’s Authorization Endpoint.
OAuth2AuthorizationRequestResolver
的主要作用是从提供的 Web 请求中解析 OAuth2AuthorizationRequest
。默认实现 DefaultOAuth2AuthorizationRequestResolver
匹配(默认)路径 /oauth2/authorization/{registrationId}
,提取 registrationId
,并使用它为关联的 ClientRegistration
构建 OAuth2AuthorizationRequest
。
The primary role of the OAuth2AuthorizationRequestResolver
is to resolve an OAuth2AuthorizationRequest
from the provided web request.
The default implementation DefaultOAuth2AuthorizationRequestResolver
matches on the (default) path /oauth2/authorization/{registrationId}
, extracting the registrationId
, and using it to build the OAuth2AuthorizationRequest
for the associated ClientRegistration
.
考虑 OAuth 2.0 客户端注册的以下 Spring Boot 2.x 属性:
Consider the following Spring Boot 2.x properties for an OAuth 2.0 Client registration:
spring:
security:
oauth2:
client:
registration:
okta:
client-id: okta-client-id
client-secret: okta-client-secret
authorization-grant-type: authorization_code
redirect-uri: "{baseUrl}/authorized/okta"
scope: read, write
provider:
okta:
authorization-uri: https://dev-1234.oktapreview.com/oauth2/v1/authorize
token-uri: https://dev-1234.oktapreview.com/oauth2/v1/token
鉴于前述属性,带有基本路径 /oauth2/authorization/okta
的请求将由 OAuth2AuthorizationRequestRedirectFilter
发起授权请求重定向并最终启动授权码授权流。
Given the preceding properties, a request with the base path /oauth2/authorization/okta
initiates the Authorization Request redirect by the OAuth2AuthorizationRequestRedirectFilter
and ultimately starts the Authorization Code grant flow.
The |
如果 OAuth 2.0 客户端是 Public Client,请按如下方式配置 OAuth 2.0 客户端注册:
If the OAuth 2.0 Client is a Public Client, configure the OAuth 2.0 Client registration as follows:
spring:
security:
oauth2:
client:
registration:
okta:
client-id: okta-client-id
client-authentication-method: none
authorization-grant-type: authorization_code
redirect-uri: "{baseUrl}/authorized/okta"
...
公有客户端得到 Proof Key for Code Exchange (PKCE) 的支持。如果客户端在不受信任的环境(例如原生应用程序或基于网络浏览器的应用程序)中运行,因此无法维持其凭据的机密性,则在满足以下条件时会自动使用 PKCE:
Public Clients are supported by using Proof Key for Code Exchange (PKCE). If the client is running in an untrusted environment (such as a native application or web browser-based application) and is therefore incapable of maintaining the confidentiality of its credentials, PKCE is automatically used when the following conditions are true:
-
client-secret
is omitted (or empty) -
client-authentication-method
is set tonone
(ClientAuthenticationMethod.NONE
)
如果 OAuth 2.0 提供方支持 Confidential Clients 的 PKCE,您可以(可选)使用 |
If the OAuth 2.0 Provider supports PKCE for Confidential Clients, you may (optionally) configure it using |
DefaultOAuth2AuthorizationRequestResolver
还使用 UriComponentsBuilder
为 redirect-uri
支持 URI
模板变量。
The DefaultOAuth2AuthorizationRequestResolver
also supports URI
template variables for the redirect-uri
by using UriComponentsBuilder
.
以下配置使用所有受支持的 URI
模板变量:
The following configuration uses all the supported URI
template variables:
spring:
security:
oauth2:
client:
registration:
okta:
...
redirect-uri: "{baseScheme}://{baseHost}{basePort}{basePath}/authorized/{registrationId}"
...
|
使用 URI
模板变量配置 redirect-uri
在 OAuth 2.0 客户端在 Proxy Server 后面运行时特别有用。这样做可确保在扩展 redirect-uri
时使用 X-Forwarded-*
头。
Configuring the redirect-uri
with URI
template variables is especially useful when the OAuth 2.0 Client is running behind a Proxy Server.
Doing so ensures that the X-Forwarded-*
headers are used when expanding the redirect-uri
.
Customizing the Authorization Request
OAuth2AuthorizationRequestResolver
可以实现的主要用例之一是能够使用 OAuth 2.0 授权框架中定义的标准参数之外的附加参数自定义授权请求。
One of the primary use cases an OAuth2AuthorizationRequestResolver
can realize is the ability to customize the Authorization Request with additional parameters above the standard parameters defined in the OAuth 2.0 Authorization Framework.
例如,OpenID Connect 为 Authorization Code Flow 定义额外的 OAuth 2.0 请求参数,该请求参数从 OAuth 2.0 Authorization Framework 中定义的标准参数扩展而来。这些扩展参数之一是 prompt
参数。
For example, OpenID Connect defines additional OAuth 2.0 request parameters for the Authorization Code Flow extending from the standard parameters defined in the OAuth 2.0 Authorization Framework.
One of those extended parameters is the prompt
parameter.
The |
以下示例显示如何使用 Consumer<OAuth2AuthorizationRequest.Builder>
配置 DefaultOAuth2AuthorizationRequestResolver
,该 Consumer<OAuth2AuthorizationRequest.Builder>
通过包括请求参数 prompt=consent
来定制 oauth2Login()
的授权请求。
The following example shows how to configure the DefaultOAuth2AuthorizationRequestResolver
with a Consumer<OAuth2AuthorizationRequest.Builder>
that customizes the Authorization Request for oauth2Login()
, by including the request parameter prompt=consent
.
-
Java
-
Kotlin
@Configuration
@EnableWebSecurity
public class OAuth2LoginSecurityConfig {
@Autowired
private ClientRegistrationRepository clientRegistrationRepository;
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests(authorize -> authorize
.anyRequest().authenticated()
)
.oauth2Login(oauth2 -> oauth2
.authorizationEndpoint(authorization -> authorization
.authorizationRequestResolver(
authorizationRequestResolver(this.clientRegistrationRepository)
)
)
);
return http.build();
}
private OAuth2AuthorizationRequestResolver authorizationRequestResolver(
ClientRegistrationRepository clientRegistrationRepository) {
DefaultOAuth2AuthorizationRequestResolver authorizationRequestResolver =
new DefaultOAuth2AuthorizationRequestResolver(
clientRegistrationRepository, "/oauth2/authorization");
authorizationRequestResolver.setAuthorizationRequestCustomizer(
authorizationRequestCustomizer());
return authorizationRequestResolver;
}
private Consumer<OAuth2AuthorizationRequest.Builder> authorizationRequestCustomizer() {
return customizer -> customizer
.additionalParameters(params -> params.put("prompt", "consent"));
}
}
@Configuration
@EnableWebSecurity
class SecurityConfig {
@Autowired
private lateinit var customClientRegistrationRepository: ClientRegistrationRepository
@Bean
open fun filterChain(http: HttpSecurity): SecurityFilterChain {
http {
authorizeRequests {
authorize(anyRequest, authenticated)
}
oauth2Login {
authorizationEndpoint {
authorizationRequestResolver = authorizationRequestResolver(customClientRegistrationRepository)
}
}
}
return http.build()
}
private fun authorizationRequestResolver(
clientRegistrationRepository: ClientRegistrationRepository?): OAuth2AuthorizationRequestResolver? {
val authorizationRequestResolver = DefaultOAuth2AuthorizationRequestResolver(
clientRegistrationRepository, "/oauth2/authorization")
authorizationRequestResolver.setAuthorizationRequestCustomizer(
authorizationRequestCustomizer())
return authorizationRequestResolver
}
private fun authorizationRequestCustomizer(): Consumer<OAuth2AuthorizationRequest.Builder> {
return Consumer { customizer ->
customizer
.additionalParameters { params -> params["prompt"] = "consent" }
}
}
}
对于附加请求参数始终对特定提供程序相同时的简单用例,您可以在 authorization-uri
属性中直接添加它。
For the simple use case where the additional request parameter is always the same for a specific provider, you can add it directly in the authorization-uri
property.
例如,如果对提供程序 okta
,请求参数 prompt
的值始终为 consent
,则可以按如下方式进行配置:
For example, if the value for the request parameter prompt
is always consent
for the provider okta
, you can configure it as follows:
spring:
security:
oauth2:
client:
provider:
okta:
authorization-uri: https://dev-1234.oktapreview.com/oauth2/v1/authorize?prompt=consent
前面的示例显示了在标准参数之上添加自定义参数的常见用例。或者,如果您的要求更高级,则可以通过覆盖 OAuth2AuthorizationRequest.authorizationRequestUri
属性来完全控制构建授权请求 URI。
The preceding example shows the common use case of adding a custom parameter on top of the standard parameters.
Alternatively, if your requirements are more advanced, you can take full control in building the Authorization Request URI by overriding the OAuth2AuthorizationRequest.authorizationRequestUri
property.
|
以下示例显示了前面示例中 authorizationRequestCustomizer()
的一个变体,相反,它覆盖了 OAuth2AuthorizationRequest.authorizationRequestUri
属性:
The following example shows a variation of authorizationRequestCustomizer()
from the preceding example and instead overrides the OAuth2AuthorizationRequest.authorizationRequestUri
property:
-
Java
-
Kotlin
private Consumer<OAuth2AuthorizationRequest.Builder> authorizationRequestCustomizer() {
return customizer -> customizer
.authorizationRequestUri(uriBuilder -> uriBuilder
.queryParam("prompt", "consent").build());
}
private fun authorizationRequestCustomizer(): Consumer<OAuth2AuthorizationRequest.Builder> {
return Consumer { customizer: OAuth2AuthorizationRequest.Builder ->
customizer
.authorizationRequestUri { uriBuilder: UriBuilder ->
uriBuilder
.queryParam("prompt", "consent").build()
}
}
}
Storing the Authorization Request
AuthorizationRequestRepository
负责从发起授权请求的时间到收到授权响应(回调)的时间对 OAuth2AuthorizationRequest
进行持久性处理。
The AuthorizationRequestRepository
is responsible for the persistence of the OAuth2AuthorizationRequest
from the time the Authorization Request is initiated to the time the Authorization Response is received (the callback).
The |
AuthorizationRequestRepository
的默认实现为 HttpSessionOAuth2AuthorizationRequestRepository
,该实现将 OAuth2AuthorizationRequest
存储在 HttpSession
中。
The default implementation of AuthorizationRequestRepository
is HttpSessionOAuth2AuthorizationRequestRepository
, which stores the OAuth2AuthorizationRequest
in the HttpSession
.
如果您具有 AuthorizationRequestRepository
的自定义实现,则可以按如下方式进行配置:
If you have a custom implementation of AuthorizationRequestRepository
, you can configure it as follows:
-
Java
-
Kotlin
-
Xml
@Configuration
@EnableWebSecurity
public class OAuth2ClientSecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.oauth2Client(oauth2 -> oauth2
.authorizationCodeGrant(codeGrant -> codeGrant
.authorizationRequestRepository(this.authorizationRequestRepository())
...
)
.oauth2Login(oauth2 -> oauth2
.authorizationEndpoint(endpoint -> endpoint
.authorizationRequestRepository(this.authorizationRequestRepository())
...
)
).build();
}
@Bean
public AuthorizationRequestRepository<OAuth2AuthorizationRequest> authorizationRequestRepository() {
return new CustomOAuth2AuthorizationRequestRepository();
}
}
@Configuration
@EnableWebSecurity
class OAuth2ClientSecurityConfig {
@Bean
open fun filterChain(http: HttpSecurity): SecurityFilterChain {
http {
oauth2Client {
authorizationCodeGrant {
authorizationRequestRepository = authorizationRequestRepository()
}
}
}
return http.build()
}
}
<http>
<oauth2-client>
<authorization-code-grant authorization-request-repository-ref="authorizationRequestRepository"/>
</oauth2-client>
</http>
Requesting an Access Token
有关授权码授权,请参阅 Access Token Request/Response 协议流程。 See the Access Token Request/Response protocol flow for the Authorization Code grant. |
授权码授权的 OAuth2AccessTokenResponseClient
的默认实现为 DefaultAuthorizationCodeTokenResponseClient
,它使用 RestOperations
实例在授权服务器令牌端点处将授权码交换为访问令牌。
The default implementation of OAuth2AccessTokenResponseClient
for the Authorization Code grant is DefaultAuthorizationCodeTokenResponseClient
, which uses a RestOperations
instance to exchange an authorization code for an access token at the Authorization Server’s Token Endpoint.
DefaultAuthorizationCodeTokenResponseClient
十分灵活,因为它允许你自定义令牌请求预处理和/或令牌响应后处理。
The DefaultAuthorizationCodeTokenResponseClient
is flexible, as it lets you customize the pre-processing of the Token Request and/or post-handling of the Token Response.
Customizing the Access Token Request
如果您需要自定义令牌请求的预处理,您可以为 DefaultAuthorizationCodeTokenResponseClient.setRequestEntityConverter()
提供自定义 Converter<OAuth2AuthorizationCodeGrantRequest, RequestEntity<?>>
。默认实施(OAuth2AuthorizationCodeGrantRequestEntityConverter
)构建标准 OAuth 2.0 Access Token Request 的 RequestEntity
表示形式。但是,提供一个自定义 Converter
将让您扩展标准令牌请求并添加自定义参数。
If you need to customize the pre-processing of the Token Request, you can provide DefaultAuthorizationCodeTokenResponseClient.setRequestEntityConverter()
with a custom Converter<OAuth2AuthorizationCodeGrantRequest, RequestEntity<?>>
.
The default implementation (OAuth2AuthorizationCodeGrantRequestEntityConverter
) builds a RequestEntity
representation of a standard OAuth 2.0 Access Token Request.
However, providing a custom Converter
would let you extend the standard Token Request and add custom parameter(s).
要仅自定义请求的参数,可以使用自定义 Converter<OAuth2AuthorizationCodeGrantRequest, MultiValueMap<String, String>>
向 OAuth2AuthorizationCodeGrantRequestEntityConverter.setParametersConverter()
提供,以完全覆盖随请求发送的参数。这通常比直接构建 RequestEntity
更简单。
To customize only the parameters of the request, you can provide OAuth2AuthorizationCodeGrantRequestEntityConverter.setParametersConverter()
with a custom Converter<OAuth2AuthorizationCodeGrantRequest, MultiValueMap<String, String>>
to completely override the parameters sent with the request. This is often simpler than constructing a RequestEntity
directly.
如果你更愿意只添加其他参数,可以使用自定义 If you prefer to only add additional parameters, you can provide |
自定义 Converter
必须返回 OAuth 2.0 访问令牌请求的有效 RequestEntity
表示,该访问令牌请求由目标 OAuth 2.0 提供商理解。
The custom Converter
must return a valid RequestEntity
representation of an OAuth 2.0 Access Token Request that is understood by the intended OAuth 2.0 Provider.
Customizing the Access Token Response
另一方面,如果你需要自定义令牌响应后处理,则需要使用自定义配置的 RestOperations
向 DefaultAuthorizationCodeTokenResponseClient.setRestOperations()
提供。默认 RestOperations
配置如下:
On the other end, if you need to customize the post-handling of the Token Response, you need to provide DefaultAuthorizationCodeTokenResponseClient.setRestOperations()
with a custom configured RestOperations
.
The default RestOperations
is configured as follows:
-
Java
-
Kotlin
RestTemplate restTemplate = new RestTemplate(Arrays.asList(
new FormHttpMessageConverter(),
new OAuth2AccessTokenResponseHttpMessageConverter()));
restTemplate.setErrorHandler(new OAuth2ErrorResponseErrorHandler());
val restTemplate = RestTemplate(listOf(
FormHttpMessageConverter(),
OAuth2AccessTokenResponseHttpMessageConverter()))
restTemplate.errorHandler = OAuth2ErrorResponseErrorHandler()
需要 Spring MVC Spring MVC |
OAuth2AccessTokenResponseHttpMessageConverter
是 OAuth 2.0 访问令牌响应的 HttpMessageConverter
。可以使用自定义 Converter<Map<String, Object>, OAuth2AccessTokenResponse>
向 OAuth2AccessTokenResponseHttpMessageConverter.setAccessTokenResponseConverter()
提供,用于将 OAuth 2.0 访问令牌响应参数转换为 OAuth2AccessTokenResponse
。
OAuth2AccessTokenResponseHttpMessageConverter
is an HttpMessageConverter
for an OAuth 2.0 Access Token Response.
You can provide OAuth2AccessTokenResponseHttpMessageConverter.setAccessTokenResponseConverter()
with a custom Converter<Map<String, Object>, OAuth2AccessTokenResponse>
that is used for converting the OAuth 2.0 Access Token Response parameters to an OAuth2AccessTokenResponse
.
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, such as 400 Bad Request
.
It uses an OAuth2ErrorHttpMessageConverter
for converting the OAuth 2.0 Error parameters to an OAuth2Error
.
无论你自定义 DefaultAuthorizationCodeTokenResponseClient
还是提供你自己的 OAuth2AccessTokenResponseClient
实施,都需要按如下方式进行配置:
Whether you customize DefaultAuthorizationCodeTokenResponseClient
or provide your own implementation of OAuth2AccessTokenResponseClient
, you need to configure it as follows:
-
Java
-
Kotlin
-
Xml
@Configuration
@EnableWebSecurity
public class OAuth2ClientSecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.oauth2Client(oauth2 -> oauth2
.authorizationCodeGrant(codeGrant -> codeGrant
.accessTokenResponseClient(this.accessTokenResponseClient())
...
)
);
return http.build();
}
}
@Configuration
@EnableWebSecurity
class OAuth2ClientSecurityConfig {
@Bean
open fun filterChain(http: HttpSecurity): SecurityFilterChain {
http {
oauth2Client {
authorizationCodeGrant {
accessTokenResponseClient = accessTokenResponseClient()
}
}
}
return http.build()
}
}
<http>
<oauth2-client>
<authorization-code-grant access-token-response-client-ref="accessTokenResponseClient"/>
</oauth2-client>
</http>
Refresh Token
有关 Refresh Token 的更多详情,请参阅 OAuth 2.0 授权框架。 See the OAuth 2.0 Authorization Framework for further details on the Refresh Token. |
Refreshing an Access Token
有关刷新令牌授权,请参阅 Access Token Request/Response 协议流程。 See the Access Token Request/Response protocol flow for the Refresh Token grant. |
OAuth2AccessTokenResponseClient
中刷新令牌授权的默认实施为 DefaultRefreshTokenTokenResponseClient
,它在授权服务器令牌端点刷新访问令牌时使用 RestOperations
。
The default implementation of OAuth2AccessTokenResponseClient
for the Refresh Token grant is DefaultRefreshTokenTokenResponseClient
, which uses a RestOperations
when refreshing an access token at the Authorization Server’s Token Endpoint.
DefaultRefreshTokenTokenResponseClient
十分灵活,因为它允许自定义令牌请求预处理或令牌响应后处理。
The DefaultRefreshTokenTokenResponseClient
is flexible, as it lets you customize the pre-processing of the Token Request or post-handling of the Token Response.
Customizing the Access Token Request
如果您需要为令牌请求自定义预处理,则可以向 DefaultRefreshTokenTokenResponseClient.setRequestEntityConverter()
提供自定义 Converter<OAuth2RefreshTokenGrantRequest, RequestEntity<?>>
。默认实现 (OAuth2RefreshTokenGrantRequestEntityConverter
) 会构建标准 OAuth 2.0 Access Token Request 的 RequestEntity
表示。但是,提供自定义 Converter
可以让您扩展标准令牌请求并添加自定义参数。
If you need to customize the pre-processing of the Token Request, you can provide DefaultRefreshTokenTokenResponseClient.setRequestEntityConverter()
with a custom Converter<OAuth2RefreshTokenGrantRequest, RequestEntity<?>>
.
The default implementation (OAuth2RefreshTokenGrantRequestEntityConverter
) builds a RequestEntity
representation of a standard OAuth 2.0 Access Token Request.
However, providing a custom Converter
would let you extend the standard Token Request and add custom parameter(s).
要仅自定义请求的参数,可以使用自定义 Converter<OAuth2RefreshTokenGrantRequest, MultiValueMap<String, String>>
向 OAuth2RefreshTokenGrantRequestEntityConverter.setParametersConverter()
提供,以完全覆盖随请求发送的参数。这通常比直接构建 RequestEntity
更简单。
To customize only the parameters of the request, you can provide OAuth2RefreshTokenGrantRequestEntityConverter.setParametersConverter()
with a custom Converter<OAuth2RefreshTokenGrantRequest, MultiValueMap<String, String>>
to completely override the parameters sent with the request. This is often simpler than constructing a RequestEntity
directly.
如果你更愿意只添加其他参数,可以使用自定义 If you prefer to only add additional parameters, you can provide |
自定义 Converter
必须返回 OAuth 2.0 访问令牌请求的有效 RequestEntity
表示,该访问令牌请求由目标 OAuth 2.0 提供商理解。
The custom Converter
must return a valid RequestEntity
representation of an OAuth 2.0 Access Token Request that is understood by the intended OAuth 2.0 Provider.
Customizing the Access Token Response
另一方面,如果你需要自定义令牌响应后处理,则需要使用自定义配置的 RestOperations
向 DefaultRefreshTokenTokenResponseClient.setRestOperations()
提供。默认 RestOperations
配置如下:
On the other end, if you need to customize the post-handling of the Token Response, you need to provide DefaultRefreshTokenTokenResponseClient.setRestOperations()
with a custom configured RestOperations
.
The default RestOperations
is configured as follows:
-
Java
-
Kotlin
RestTemplate restTemplate = new RestTemplate(Arrays.asList(
new FormHttpMessageConverter(),
new OAuth2AccessTokenResponseHttpMessageConverter()));
restTemplate.setErrorHandler(new OAuth2ErrorResponseErrorHandler());
val restTemplate = RestTemplate(listOf(
FormHttpMessageConverter(),
OAuth2AccessTokenResponseHttpMessageConverter()))
restTemplate.errorHandler = OAuth2ErrorResponseErrorHandler()
需要 Spring MVC Spring MVC |
OAuth2AccessTokenResponseHttpMessageConverter
是 OAuth 2.0 访问令牌响应的 HttpMessageConverter
。可以使用自定义 Converter<Map<String, Object>, OAuth2AccessTokenResponse>
向 OAuth2AccessTokenResponseHttpMessageConverter.setAccessTokenResponseConverter()
提供,用于将 OAuth 2.0 访问令牌响应参数转换为 OAuth2AccessTokenResponse
。
OAuth2AccessTokenResponseHttpMessageConverter
is a HttpMessageConverter
for an OAuth 2.0 Access Token Response.
You can provide OAuth2AccessTokenResponseHttpMessageConverter.setAccessTokenResponseConverter()
with a custom Converter<Map<String, Object>, OAuth2AccessTokenResponse>
that is used for converting the OAuth 2.0 Access Token Response parameters to an OAuth2AccessTokenResponse
.
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, such as 400 Bad Request
.
It uses an OAuth2ErrorHttpMessageConverter
for converting the OAuth 2.0 Error parameters to an OAuth2Error
.
无论你自定义 DefaultRefreshTokenTokenResponseClient
还是提供你自己的 OAuth2AccessTokenResponseClient
实施,都需要按如下方式进行配置:
Whether you customize DefaultRefreshTokenTokenResponseClient
or provide your own implementation of OAuth2AccessTokenResponseClient
, you need to configure it as follows:
-
Java
-
Kotlin
// Customize
OAuth2AccessTokenResponseClient<OAuth2RefreshTokenGrantRequest> refreshTokenTokenResponseClient = ...
OAuth2AuthorizedClientProvider authorizedClientProvider =
OAuth2AuthorizedClientProviderBuilder.builder()
.authorizationCode()
.refreshToken(configurer -> configurer.accessTokenResponseClient(refreshTokenTokenResponseClient))
.build();
...
authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider);
// Customize
val refreshTokenTokenResponseClient: OAuth2AccessTokenResponseClient<OAuth2RefreshTokenGrantRequest> = ...
val authorizedClientProvider = OAuth2AuthorizedClientProviderBuilder.builder()
.authorizationCode()
.refreshToken { it.accessTokenResponseClient(refreshTokenTokenResponseClient) }
.build()
...
authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider)
|
对于 authorization_code
和 password
授权类型,选项为在 Access Token 响应中返回 OAuth2RefreshToken
。如果 OAuth2AuthorizedClient.getRefreshToken()
可用,且 OAuth2AuthorizedClient.getAccessToken()
已过期,则 RefreshTokenOAuth2AuthorizedClientProvider
会自动刷新它。
The OAuth2RefreshToken
can optionally be returned in the Access Token Response for the authorization_code
and password
grant types.
If the OAuth2AuthorizedClient.getRefreshToken()
is available and the OAuth2AuthorizedClient.getAccessToken()
is expired, it is automatically refreshed by the RefreshTokenOAuth2AuthorizedClientProvider
.
Client Credentials
请参阅 OAuth 2.0 授权框架,进一步了解 Client Credentials 授权。 |
Please refer to the OAuth 2.0 Authorization Framework for further details on the Client Credentials grant. |
Requesting an Access Token
请参阅 OAuth 2.0 授权框架以详细了解 Client Credentials 授权。 See the OAuth 2.0 Authorization Framework for further details on the Client Credentials grant. |
OAuth2AccessTokenResponseClient
的默认实现是 Client Credentials 授权的 DefaultClientCredentialsTokenResponseClient
,它在 Authorization Server 的 Token 终端请求访问令牌时使用 RestOperations
。
The default implementation of OAuth2AccessTokenResponseClient
for the Client Credentials grant is DefaultClientCredentialsTokenResponseClient
, which uses a RestOperations
when requesting an access token at the Authorization Server’s Token Endpoint.
DefaultClientCredentialsTokenResponseClient
是灵活的,因为它允许您自定义令牌请求的预处理或令牌响应的后处理。
The DefaultClientCredentialsTokenResponseClient
is flexible, as it lets you customize the pre-processing of the Token Request or post-handling of the Token Response.
Customizing the Access Token Request
如果您需要为令牌请求自定义预处理,则可以向 DefaultClientCredentialsTokenResponseClient.setRequestEntityConverter()
提供自定义 Converter<OAuth2ClientCredentialsGrantRequest, RequestEntity<?>>
。默认实现 (OAuth2ClientCredentialsGrantRequestEntityConverter
) 会构建标准 OAuth 2.0 Access Token Request 的 RequestEntity
表示。但是,提供自定义 Converter
可以让您扩展标准令牌请求并添加自定义参数。
If you need to customize the pre-processing of the Token Request, you can provide DefaultClientCredentialsTokenResponseClient.setRequestEntityConverter()
with a custom Converter<OAuth2ClientCredentialsGrantRequest, RequestEntity<?>>
.
The default implementation (OAuth2ClientCredentialsGrantRequestEntityConverter
) builds a RequestEntity
representation of a standard OAuth 2.0 Access Token Request.
However, providing a custom Converter
would let you extend the standard Token Request and add custom parameter(s).
要仅自定义请求的参数,您可以为 OAuth2ClientCredentialsGrantRequestEntityConverter.setParametersConverter()
提供一个自定义的 Converter<OAuth2ClientCredentialsGrantRequest, MultiValueMap<String, String>>
,以完全覆盖随请求发送的参数。这通常比直接构建 RequestEntity
更加容易。
To customize only the parameters of the request, you can provide OAuth2ClientCredentialsGrantRequestEntityConverter.setParametersConverter()
with a custom Converter<OAuth2ClientCredentialsGrantRequest, MultiValueMap<String, String>>
to completely override the parameters sent with the request. This is often simpler than constructing a RequestEntity
directly.
如果您只想添加其他的参数,您可以为 If you prefer to only add additional parameters, you can provide |
自定义 Converter
必须返回 OAuth 2.0 访问令牌请求的有效 RequestEntity
表示,该访问令牌请求由目标 OAuth 2.0 提供商理解。
The custom Converter
must return a valid RequestEntity
representation of an OAuth 2.0 Access Token Request that is understood by the intended OAuth 2.0 Provider.
Customizing the Access Token Response
另一方面,如果您需要自定义令牌响应的后处理,则需要为 DefaultClientCredentialsTokenResponseClient.setRestOperations()
提供一个自定义配置的 RestOperations
。默认 RestOperations
配置如下:
On the other end, if you need to customize the post-handling of the Token Response, you need to provide DefaultClientCredentialsTokenResponseClient.setRestOperations()
with a custom configured RestOperations
.
The default RestOperations
is configured as follows:
-
Java
-
Kotlin
RestTemplate restTemplate = new RestTemplate(Arrays.asList(
new FormHttpMessageConverter(),
new OAuth2AccessTokenResponseHttpMessageConverter()));
restTemplate.setErrorHandler(new OAuth2ErrorResponseErrorHandler());
val restTemplate = RestTemplate(listOf(
FormHttpMessageConverter(),
OAuth2AccessTokenResponseHttpMessageConverter()))
restTemplate.errorHandler = OAuth2ErrorResponseErrorHandler()
需要 Spring MVC Spring MVC |
OAuth2AccessTokenResponseHttpMessageConverter
是 OAuth 2.0 访问令牌响应的 HttpMessageConverter
。可以使用自定义 Converter<Map<String, Object>, OAuth2AccessTokenResponse>
向 OAuth2AccessTokenResponseHttpMessageConverter.setAccessTokenResponseConverter()
提供,用于将 OAuth 2.0 访问令牌响应参数转换为 OAuth2AccessTokenResponse
。
OAuth2AccessTokenResponseHttpMessageConverter
is a HttpMessageConverter
for an OAuth 2.0 Access Token Response.
You can provide OAuth2AccessTokenResponseHttpMessageConverter.setAccessTokenResponseConverter()
with a custom Converter<Map<String, Object>, OAuth2AccessTokenResponse>
that is used for converting the OAuth 2.0 Access Token Response parameters to an OAuth2AccessTokenResponse
.
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, such as 400 Bad Request
.
It uses an OAuth2ErrorHttpMessageConverter
to convert the OAuth 2.0 Error parameters to an OAuth2Error
.
无论您是自定义 DefaultClientCredentialsTokenResponseClient
还是提供您自己的 OAuth2AccessTokenResponseClient
实现方法,都需要按照如下所述配置它:
Whether you customize DefaultClientCredentialsTokenResponseClient
or provide your own implementation of OAuth2AccessTokenResponseClient
, you need to configure it as follows:
-
Java
-
Kotlin
// Customize
OAuth2AccessTokenResponseClient<OAuth2ClientCredentialsGrantRequest> clientCredentialsTokenResponseClient = ...
OAuth2AuthorizedClientProvider authorizedClientProvider =
OAuth2AuthorizedClientProviderBuilder.builder()
.clientCredentials(configurer -> configurer.accessTokenResponseClient(clientCredentialsTokenResponseClient))
.build();
...
authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider);
// Customize
val clientCredentialsTokenResponseClient: OAuth2AccessTokenResponseClient<OAuth2ClientCredentialsGrantRequest> = ...
val authorizedClientProvider = OAuth2AuthorizedClientProviderBuilder.builder()
.clientCredentials { it.accessTokenResponseClient(clientCredentialsTokenResponseClient) }
.build()
...
authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider)
|
Using the Access Token
考虑 OAuth 2.0 客户端注册的以下 Spring Boot 2.x 属性:
Consider the following Spring Boot 2.x properties for an OAuth 2.0 Client registration:
spring:
security:
oauth2:
client:
registration:
okta:
client-id: okta-client-id
client-secret: okta-client-secret
authorization-grant-type: client_credentials
scope: read, write
provider:
okta:
token-uri: https://dev-1234.oktapreview.com/oauth2/v1/token
进一步考虑以下 OAuth2AuthorizedClientManager
@Bean
:
Further consider the following OAuth2AuthorizedClientManager
@Bean
:
-
Java
-
Kotlin
@Bean
public OAuth2AuthorizedClientManager authorizedClientManager(
ClientRegistrationRepository clientRegistrationRepository,
OAuth2AuthorizedClientRepository authorizedClientRepository) {
OAuth2AuthorizedClientProvider authorizedClientProvider =
OAuth2AuthorizedClientProviderBuilder.builder()
.clientCredentials()
.build();
DefaultOAuth2AuthorizedClientManager authorizedClientManager =
new DefaultOAuth2AuthorizedClientManager(
clientRegistrationRepository, authorizedClientRepository);
authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider);
return authorizedClientManager;
}
@Bean
fun authorizedClientManager(
clientRegistrationRepository: ClientRegistrationRepository,
authorizedClientRepository: OAuth2AuthorizedClientRepository): OAuth2AuthorizedClientManager {
val authorizedClientProvider = OAuth2AuthorizedClientProviderBuilder.builder()
.clientCredentials()
.build()
val authorizedClientManager = DefaultOAuth2AuthorizedClientManager(
clientRegistrationRepository, authorizedClientRepository)
authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider)
return authorizedClientManager
}
鉴于前面的属性和 bean,您可以按照如下方式获取 OAuth2AccessToken
:
Given the preceding properties and bean, you can obtain the OAuth2AccessToken
as follows:
-
Java
-
Kotlin
@Controller
public class OAuth2ClientController {
@Autowired
private OAuth2AuthorizedClientManager authorizedClientManager;
@GetMapping("/")
public String index(Authentication authentication,
HttpServletRequest servletRequest,
HttpServletResponse servletResponse) {
OAuth2AuthorizeRequest authorizeRequest = OAuth2AuthorizeRequest.withClientRegistrationId("okta")
.principal(authentication)
.attributes(attrs -> {
attrs.put(HttpServletRequest.class.getName(), servletRequest);
attrs.put(HttpServletResponse.class.getName(), servletResponse);
})
.build();
OAuth2AuthorizedClient authorizedClient = this.authorizedClientManager.authorize(authorizeRequest);
OAuth2AccessToken accessToken = authorizedClient.getAccessToken();
...
return "index";
}
}
class OAuth2ClientController {
@Autowired
private lateinit var authorizedClientManager: OAuth2AuthorizedClientManager
@GetMapping("/")
fun index(authentication: Authentication?,
servletRequest: HttpServletRequest,
servletResponse: HttpServletResponse): String {
val authorizeRequest: OAuth2AuthorizeRequest = OAuth2AuthorizeRequest.withClientRegistrationId("okta")
.principal(authentication)
.attributes(Consumer { attrs: MutableMap<String, Any> ->
attrs[HttpServletRequest::class.java.name] = servletRequest
attrs[HttpServletResponse::class.java.name] = servletResponse
})
.build()
val authorizedClient = authorizedClientManager.authorize(authorizeRequest)
val accessToken: OAuth2AccessToken = authorizedClient.accessToken
...
return "index"
}
}
|
Resource Owner Password Credentials
请参阅 OAuth 2.0 授权框架以详细了解 Resource Owner Password Credentials 授权。 See the OAuth 2.0 Authorization Framework for further details on the Resource Owner Password Credentials grant. |
Requesting an Access Token
请参阅 Access Token Request/Response 协议流程以了解资源所有者密码凭据授权。 See the Access Token Request/Response protocol flow for the Resource Owner Password Credentials grant. |
OAuth2AccessTokenResponseClient
的默认实现是资源所有者密码凭证授权的 DefaultPasswordTokenResponseClient
,它在 Authorization Server 的 Token 终端请求访问令牌时使用 RestOperations
。
The default implementation of OAuth2AccessTokenResponseClient
for the Resource Owner Password Credentials grant is DefaultPasswordTokenResponseClient
, which uses a RestOperations
when requesting an access token at the Authorization Server’s Token Endpoint.
DefaultPasswordTokenResponseClient
是灵活的,因为它允许您自定义令牌请求的预处理或令牌响应的后处理。
The DefaultPasswordTokenResponseClient
is flexible, as it lets you customize the pre-processing of the Token Request or post-handling of the Token Response.
Customizing the Access Token Request
如果您需要为令牌请求自定义预处理,则可以向 DefaultPasswordTokenResponseClient.setRequestEntityConverter()
提供自定义 Converter<OAuth2PasswordGrantRequest, RequestEntity<?>>
。默认实现 (OAuth2PasswordGrantRequestEntityConverter
) 会构建标准 OAuth 2.0 Access Token Request 的 RequestEntity
表示。但是,提供自定义 Converter
可以让您扩展标准令牌请求并添加自定义参数。
If you need to customize the pre-processing of the Token Request, you can provide DefaultPasswordTokenResponseClient.setRequestEntityConverter()
with a custom Converter<OAuth2PasswordGrantRequest, RequestEntity<?>>
.
The default implementation (OAuth2PasswordGrantRequestEntityConverter
) builds a RequestEntity
representation of a standard OAuth 2.0 Access Token Request.
However, providing a custom Converter
would let you extend the standard Token Request and add custom parameter(s).
要仅自定义请求的参数,可为 OAuth2PasswordGrantRequestEntityConverter.setParametersConverter()
提供自定义 Converter<OAuth2PasswordGrantRequest, MultiValueMap<String, String>>
以完全覆盖使用该请求发送的参数。这通常比直接构建 RequestEntity
更加简单。
To customize only the parameters of the request, you can provide OAuth2PasswordGrantRequestEntityConverter.setParametersConverter()
with a custom Converter<OAuth2PasswordGrantRequest, MultiValueMap<String, String>>
to completely override the parameters sent with the request. This is often simpler than constructing a RequestEntity
directly.
如果你只添加附加参数,可为 If you prefer to only add additional parameters, you can provide |
自定义 Converter
必须返回 OAuth 2.0 访问令牌请求的有效 RequestEntity
表示,该访问令牌请求由目标 OAuth 2.0 提供商理解。
The custom Converter
must return a valid RequestEntity
representation of an OAuth 2.0 Access Token Request that is understood by the intended OAuth 2.0 Provider.
Customizing the Access Token Response
另一方面,如果你需要自定义令牌响应的后处理,需要使用自定义配置的 RestOperations
为 DefaultPasswordTokenResponseClient.setRestOperations()
提供。默认 RestOperations
的配置如下:
On the other end, if you need to customize the post-handling of the Token Response, you need to provide DefaultPasswordTokenResponseClient.setRestOperations()
with a custom configured RestOperations
.
The default RestOperations
is configured as follows:
-
Java
-
Kotlin
RestTemplate restTemplate = new RestTemplate(Arrays.asList(
new FormHttpMessageConverter(),
new OAuth2AccessTokenResponseHttpMessageConverter()));
restTemplate.setErrorHandler(new OAuth2ErrorResponseErrorHandler());
val restTemplate = RestTemplate(listOf(
FormHttpMessageConverter(),
OAuth2AccessTokenResponseHttpMessageConverter()))
restTemplate.errorHandler = OAuth2ErrorResponseErrorHandler()
需要 Spring MVC Spring MVC |
OAuth2AccessTokenResponseHttpMessageConverter
是 OAuth 2.0 访问令牌响应的 HttpMessageConverter
。可为 OAuth2AccessTokenResponseHttpMessageConverter.setTokenResponseConverter()
提供自定义 Converter<Map<String, String>, OAuth2AccessTokenResponse>
,它用于将 OAuth 2.0 访问令牌响应参数转换为 OAuth2AccessTokenResponse
。
OAuth2AccessTokenResponseHttpMessageConverter
is a HttpMessageConverter
for an OAuth 2.0 Access Token Response.
You can provide OAuth2AccessTokenResponseHttpMessageConverter.setTokenResponseConverter()
with a custom Converter<Map<String, String>, OAuth2AccessTokenResponse>
that is used to convert the OAuth 2.0 Access Token Response parameters to an OAuth2AccessTokenResponse
.
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, such as 400 Bad Request
.
It uses an OAuth2ErrorHttpMessageConverter
to convert the OAuth 2.0 Error parameters to an OAuth2Error
.
无论你自定义 DefaultPasswordTokenResponseClient
或提供 OAuth2AccessTokenResponseClient
自己的实现,都需要按照以下方式进行配置:
Whether you customize DefaultPasswordTokenResponseClient
or provide your own implementation of OAuth2AccessTokenResponseClient
, you need to configure it as follows:
-
Java
-
Kotlin
// Customize
OAuth2AccessTokenResponseClient<OAuth2PasswordGrantRequest> passwordTokenResponseClient = ...
OAuth2AuthorizedClientProvider authorizedClientProvider =
OAuth2AuthorizedClientProviderBuilder.builder()
.password(configurer -> configurer.accessTokenResponseClient(passwordTokenResponseClient))
.refreshToken()
.build();
...
authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider);
val passwordTokenResponseClient: OAuth2AccessTokenResponseClient<OAuth2PasswordGrantRequest> = ...
val authorizedClientProvider = OAuth2AuthorizedClientProviderBuilder.builder()
.password { it.accessTokenResponseClient(passwordTokenResponseClient) }
.refreshToken()
.build()
...
authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider)
|
Using the Access Token
考虑 OAuth 2.0 客户端注册的以下 Spring Boot 2.x 属性:
Consider the following Spring Boot 2.x properties for an OAuth 2.0 Client registration:
spring:
security:
oauth2:
client:
registration:
okta:
client-id: okta-client-id
client-secret: okta-client-secret
authorization-grant-type: password
scope: read, write
provider:
okta:
token-uri: https://dev-1234.oktapreview.com/oauth2/v1/token
此外,还需要考虑 OAuth2AuthorizedClientManager
@Bean
:
Further consider the OAuth2AuthorizedClientManager
@Bean
:
-
Java
-
Kotlin
@Bean
public OAuth2AuthorizedClientManager authorizedClientManager(
ClientRegistrationRepository clientRegistrationRepository,
OAuth2AuthorizedClientRepository authorizedClientRepository) {
OAuth2AuthorizedClientProvider authorizedClientProvider =
OAuth2AuthorizedClientProviderBuilder.builder()
.password()
.refreshToken()
.build();
DefaultOAuth2AuthorizedClientManager authorizedClientManager =
new DefaultOAuth2AuthorizedClientManager(
clientRegistrationRepository, authorizedClientRepository);
authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider);
// Assuming the `username` and `password` are supplied as `HttpServletRequest` parameters,
// map the `HttpServletRequest` parameters to `OAuth2AuthorizationContext.getAttributes()`
authorizedClientManager.setContextAttributesMapper(contextAttributesMapper());
return authorizedClientManager;
}
private Function<OAuth2AuthorizeRequest, Map<String, Object>> contextAttributesMapper() {
return authorizeRequest -> {
Map<String, Object> contextAttributes = Collections.emptyMap();
HttpServletRequest servletRequest = authorizeRequest.getAttribute(HttpServletRequest.class.getName());
String username = servletRequest.getParameter(OAuth2ParameterNames.USERNAME);
String password = servletRequest.getParameter(OAuth2ParameterNames.PASSWORD);
if (StringUtils.hasText(username) && StringUtils.hasText(password)) {
contextAttributes = new HashMap<>();
// `PasswordOAuth2AuthorizedClientProvider` requires both attributes
contextAttributes.put(OAuth2AuthorizationContext.USERNAME_ATTRIBUTE_NAME, username);
contextAttributes.put(OAuth2AuthorizationContext.PASSWORD_ATTRIBUTE_NAME, password);
}
return contextAttributes;
};
}
@Bean
fun authorizedClientManager(
clientRegistrationRepository: ClientRegistrationRepository,
authorizedClientRepository: OAuth2AuthorizedClientRepository): OAuth2AuthorizedClientManager {
val authorizedClientProvider = OAuth2AuthorizedClientProviderBuilder.builder()
.password()
.refreshToken()
.build()
val authorizedClientManager = DefaultOAuth2AuthorizedClientManager(
clientRegistrationRepository, authorizedClientRepository)
authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider)
// Assuming the `username` and `password` are supplied as `HttpServletRequest` parameters,
// map the `HttpServletRequest` parameters to `OAuth2AuthorizationContext.getAttributes()`
authorizedClientManager.setContextAttributesMapper(contextAttributesMapper())
return authorizedClientManager
}
private fun contextAttributesMapper(): Function<OAuth2AuthorizeRequest, MutableMap<String, Any>> {
return Function { authorizeRequest ->
var contextAttributes: MutableMap<String, Any> = mutableMapOf()
val servletRequest: HttpServletRequest = authorizeRequest.getAttribute(HttpServletRequest::class.java.name)
val username = servletRequest.getParameter(OAuth2ParameterNames.USERNAME)
val password = servletRequest.getParameter(OAuth2ParameterNames.PASSWORD)
if (StringUtils.hasText(username) && StringUtils.hasText(password)) {
contextAttributes = hashMapOf()
// `PasswordOAuth2AuthorizedClientProvider` requires both attributes
contextAttributes[OAuth2AuthorizationContext.USERNAME_ATTRIBUTE_NAME] = username
contextAttributes[OAuth2AuthorizationContext.PASSWORD_ATTRIBUTE_NAME] = password
}
contextAttributes
}
}
鉴于前面的属性和 bean,您可以按照如下方式获取 OAuth2AccessToken
:
Given the preceding properties and bean, you can obtain the OAuth2AccessToken
as follows:
-
Java
-
Kotlin
@Controller
public class OAuth2ClientController {
@Autowired
private OAuth2AuthorizedClientManager authorizedClientManager;
@GetMapping("/")
public String index(Authentication authentication,
HttpServletRequest servletRequest,
HttpServletResponse servletResponse) {
OAuth2AuthorizeRequest authorizeRequest = OAuth2AuthorizeRequest.withClientRegistrationId("okta")
.principal(authentication)
.attributes(attrs -> {
attrs.put(HttpServletRequest.class.getName(), servletRequest);
attrs.put(HttpServletResponse.class.getName(), servletResponse);
})
.build();
OAuth2AuthorizedClient authorizedClient = this.authorizedClientManager.authorize(authorizeRequest);
OAuth2AccessToken accessToken = authorizedClient.getAccessToken();
...
return "index";
}
}
@Controller
class OAuth2ClientController {
@Autowired
private lateinit var authorizedClientManager: OAuth2AuthorizedClientManager
@GetMapping("/")
fun index(authentication: Authentication?,
servletRequest: HttpServletRequest,
servletResponse: HttpServletResponse): String {
val authorizeRequest: OAuth2AuthorizeRequest = OAuth2AuthorizeRequest.withClientRegistrationId("okta")
.principal(authentication)
.attributes(Consumer {
it[HttpServletRequest::class.java.name] = servletRequest
it[HttpServletResponse::class.java.name] = servletResponse
})
.build()
val authorizedClient = authorizedClientManager.authorize(authorizeRequest)
val accessToken: OAuth2AccessToken = authorizedClient.accessToken
...
return "index"
}
}
|
JWT Bearer
请参阅 JSON Web Token (JWT) OAuth 2.0 客户端认证和认证授予简介以详细了解 JWT Bearer 授权。 Please refer to JSON Web Token (JWT) Profile for OAuth 2.0 Client Authentication and Authorization Grants for further details on the JWT Bearer grant. |
Requesting an Access Token
请参阅 Access Token Request/Response 协议流程以了解 JWT 持有者授权。 Please refer to the Access Token Request/Response protocol flow for the JWT Bearer grant. |
OAuth2AccessTokenResponseClient
用于 JWT 持有者的默认实现为 DefaultJwtBearerTokenResponseClient
,它在授权服务器的令牌端点请求访问令牌时使用 RestOperations
。
The default implementation of OAuth2AccessTokenResponseClient
for the JWT Bearer grant is DefaultJwtBearerTokenResponseClient
, which uses a RestOperations
when requesting an access token at the Authorization Server’s Token Endpoint.
DefaultJwtBearerTokenResponseClient
非常灵活,因为它允许你自定义令牌请求的预处理和/或令牌响应的后处理。
The DefaultJwtBearerTokenResponseClient
is quite flexible as it allows you to customize the pre-processing of the Token Request and/or post-handling of the Token Response.
Customizing the Access Token Request
如果您需要为令牌请求自定义预处理,则可以向 DefaultJwtBearerTokenResponseClient.setRequestEntityConverter()
提供自定义 Converter<JwtBearerGrantRequest, RequestEntity<?>>
。默认实现 JwtBearerGrantRequestEntityConverter
会构建 OAuth 2.0 Access Token Request 的 RequestEntity
表示。但是,提供自定义 Converter
可以让您扩展令牌请求并添加自定义参数。
If you need to customize the pre-processing of the Token Request, you can provide DefaultJwtBearerTokenResponseClient.setRequestEntityConverter()
with a custom Converter<JwtBearerGrantRequest, RequestEntity<?>>
.
The default implementation JwtBearerGrantRequestEntityConverter
builds a RequestEntity
representation of a OAuth 2.0 Access Token Request.
However, providing a custom Converter
, would allow you to extend the Token Request and add custom parameter(s).
要仅自定义请求的参数,可为 JwtBearerGrantRequestEntityConverter.setParametersConverter()
提供自定义 Converter<JwtBearerGrantRequest, MultiValueMap<String, String>>
以完全覆盖使用该请求发送的参数。这通常比直接构建 RequestEntity
更加简单。
To customize only the parameters of the request, you can provide JwtBearerGrantRequestEntityConverter.setParametersConverter()
with a custom Converter<JwtBearerGrantRequest, MultiValueMap<String, String>>
to completely override the parameters sent with the request. This is often simpler than constructing a RequestEntity
directly.
如果您愿意仅添加其他参数,可以为 |
If you prefer to only add additional parameters, you can provide |
Customizing the Access Token Response
另一方面,如果你需要自定义令牌响应的后处理,将需要使用自定义配置的 RestOperations
为 DefaultJwtBearerTokenResponseClient.setRestOperations()
提供。默认 RestOperations
的配置如下:
On the other end, if you need to customize the post-handling of the Token Response, you will need to provide DefaultJwtBearerTokenResponseClient.setRestOperations()
with a custom configured RestOperations
.
The default RestOperations
is configured as follows:
-
Java
-
Kotlin
RestTemplate restTemplate = new RestTemplate(Arrays.asList(
new FormHttpMessageConverter(),
new OAuth2AccessTokenResponseHttpMessageConverter()));
restTemplate.setErrorHandler(new OAuth2ErrorResponseErrorHandler());
val restTemplate = RestTemplate(listOf(
FormHttpMessageConverter(),
OAuth2AccessTokenResponseHttpMessageConverter()))
restTemplate.errorHandler = OAuth2ErrorResponseErrorHandler()
需要 Spring MVC Spring MVC |
OAuth2AccessTokenResponseHttpMessageConverter
是 OAuth 2.0 访问令牌响应的 HttpMessageConverter
。可以使用自定义 Converter<Map<String, Object>, OAuth2AccessTokenResponse>
向 OAuth2AccessTokenResponseHttpMessageConverter.setAccessTokenResponseConverter()
提供,用于将 OAuth 2.0 访问令牌响应参数转换为 OAuth2AccessTokenResponse
。
OAuth2AccessTokenResponseHttpMessageConverter
is a HttpMessageConverter
for an OAuth 2.0 Access Token Response.
You can provide OAuth2AccessTokenResponseHttpMessageConverter.setAccessTokenResponseConverter()
with a custom Converter<Map<String, Object>, OAuth2AccessTokenResponse>
that is used for converting the OAuth 2.0 Access Token Response parameters to an OAuth2AccessTokenResponse
.
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, eg. 400 Bad Request.
It uses an OAuth2ErrorHttpMessageConverter
for converting the OAuth 2.0 Error parameters to an OAuth2Error
.
无论你自定义 DefaultJwtBearerTokenResponseClient
或提供 OAuth2AccessTokenResponseClient
自己的实现,都需要按照以下示例所示对其进行配置:
Whether you customize DefaultJwtBearerTokenResponseClient
or provide your own implementation of OAuth2AccessTokenResponseClient
, you’ll need to configure it as shown in the following example:
-
Java
-
Kotlin
// Customize
OAuth2AccessTokenResponseClient<JwtBearerGrantRequest> jwtBearerTokenResponseClient = ...
JwtBearerOAuth2AuthorizedClientProvider jwtBearerAuthorizedClientProvider = new JwtBearerOAuth2AuthorizedClientProvider();
jwtBearerAuthorizedClientProvider.setAccessTokenResponseClient(jwtBearerTokenResponseClient);
OAuth2AuthorizedClientProvider authorizedClientProvider =
OAuth2AuthorizedClientProviderBuilder.builder()
.provider(jwtBearerAuthorizedClientProvider)
.build();
...
authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider);
// Customize
val jwtBearerTokenResponseClient: OAuth2AccessTokenResponseClient<JwtBearerGrantRequest> = ...
val jwtBearerAuthorizedClientProvider = JwtBearerOAuth2AuthorizedClientProvider()
jwtBearerAuthorizedClientProvider.setAccessTokenResponseClient(jwtBearerTokenResponseClient);
val authorizedClientProvider = OAuth2AuthorizedClientProviderBuilder.builder()
.provider(jwtBearerAuthorizedClientProvider)
.build()
...
authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider)
Using the Access Token
给定 OAuth 2.0 客户端注册的以下 Spring Boot 2.x 属性:
Given the following Spring Boot 2.x properties for an OAuth 2.0 Client registration:
spring:
security:
oauth2:
client:
registration:
okta:
client-id: okta-client-id
client-secret: okta-client-secret
authorization-grant-type: urn:ietf:params:oauth:grant-type:jwt-bearer
scope: read
provider:
okta:
token-uri: https://dev-1234.oktapreview.com/oauth2/v1/token
…和 OAuth2AuthorizedClientManager
@Bean
:
…and the OAuth2AuthorizedClientManager
@Bean
:
-
Java
-
Kotlin
@Bean
public OAuth2AuthorizedClientManager authorizedClientManager(
ClientRegistrationRepository clientRegistrationRepository,
OAuth2AuthorizedClientRepository authorizedClientRepository) {
JwtBearerOAuth2AuthorizedClientProvider jwtBearerAuthorizedClientProvider =
new JwtBearerOAuth2AuthorizedClientProvider();
OAuth2AuthorizedClientProvider authorizedClientProvider =
OAuth2AuthorizedClientProviderBuilder.builder()
.provider(jwtBearerAuthorizedClientProvider)
.build();
DefaultOAuth2AuthorizedClientManager authorizedClientManager =
new DefaultOAuth2AuthorizedClientManager(
clientRegistrationRepository, authorizedClientRepository);
authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider);
return authorizedClientManager;
}
@Bean
fun authorizedClientManager(
clientRegistrationRepository: ClientRegistrationRepository,
authorizedClientRepository: OAuth2AuthorizedClientRepository): OAuth2AuthorizedClientManager {
val jwtBearerAuthorizedClientProvider = JwtBearerOAuth2AuthorizedClientProvider()
val authorizedClientProvider = OAuth2AuthorizedClientProviderBuilder.builder()
.provider(jwtBearerAuthorizedClientProvider)
.build()
val authorizedClientManager = DefaultOAuth2AuthorizedClientManager(
clientRegistrationRepository, authorizedClientRepository)
authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider)
return authorizedClientManager
}
可按如下方式获取 OAuth2AccessToken
:
You may obtain the OAuth2AccessToken
as follows:
-
Java
-
Kotlin
@RestController
public class OAuth2ResourceServerController {
@Autowired
private OAuth2AuthorizedClientManager authorizedClientManager;
@GetMapping("/resource")
public String resource(JwtAuthenticationToken jwtAuthentication) {
OAuth2AuthorizeRequest authorizeRequest = OAuth2AuthorizeRequest.withClientRegistrationId("okta")
.principal(jwtAuthentication)
.build();
OAuth2AuthorizedClient authorizedClient = this.authorizedClientManager.authorize(authorizeRequest);
OAuth2AccessToken accessToken = authorizedClient.getAccessToken();
...
}
}
class OAuth2ResourceServerController {
@Autowired
private lateinit var authorizedClientManager: OAuth2AuthorizedClientManager
@GetMapping("/resource")
fun resource(jwtAuthentication: JwtAuthenticationToken?): String {
val authorizeRequest: OAuth2AuthorizeRequest = OAuth2AuthorizeRequest.withClientRegistrationId("okta")
.principal(jwtAuthentication)
.build()
val authorizedClient = authorizedClientManager.authorize(authorizeRequest)
val accessToken: OAuth2AccessToken = authorizedClient.accessToken
...
}
}
|
|
如果您需要从不同来源解析 |
If you need to resolve the |