OAuth 2.0 Resource Server
Spring Security 支持使用两种形式的 OAuth 2.0 Bearer Tokens 来保护端点:
Spring Security supports protecting endpoints by using two forms of OAuth 2.0 Bearer Tokens:
-
Opaque Tokens
在应用程序已将自己的权限管理委派给 authorization server 的情况下(例如,Okta 或 Ping Identity),这会很方便。此授权服务器可以接受资源服务器的咨询,以授权请求。
This is handy in circumstances where an application has delegated its authority management to an authorization server (for example, Okta or Ping Identity). This authorization server can be consulted by resource servers to authorize requests.
该部分详细介绍了 Spring Security 如何提供对 OAuth 2.0 Bearer Tokens 的支持。
This section details how Spring Security provides support for OAuth 2.0 Bearer Tokens.
有关 JWT 和 不透明令牌 的工作示例,可以在 Spring Security Samples 存储库 中获得。 Working samples for both JWTs and Opaque Tokens are available in the Spring Security Samples repository. |
现在我们可以考虑持有者令牌身份验证如何在 Spring Security 中工作。首先,我们看到,与 Basic Authentication 一样, WWW-Authenticate 标头被发送回未经身份验证的客户端:
Now we can consider how Bearer Token Authentication works within Spring Security. First, we see that, as with Basic Authentication, the WWW-Authenticate header is sent back to an unauthenticated client:
上图建立在我们的 SecurityFilterChain
图基础上。
The figure above builds off our SecurityFilterChain
diagram.
首先,用户向 /private
资源(用户未经授权)提出了未经身份验证的请求。
First, a user makes an unauthenticated request to the /private
resource for which the user is not authorized.
Spring Security 的 AuthorizationFilter
指出未经身份验证的请求 Denied 抛出了 AccessDeniedException
。
Spring Security’s AuthorizationFilter
indicates that the unauthenticated request is Denied by throwing an AccessDeniedException
.
由于用户未经身份验证,ExceptionTranslationFilter
初始化 Start Authentication。已配置的 AuthenticationEntryPoint
是 {security-api-url}org/springframework/security/oauth2/server/resource/authentication/BearerTokenAuthenticationEntryPoint.html[BearerTokenAuthenticationEntryPoint
] 的一个实例,它发送一个 WWW-Authenticate
标头。RequestCache
通常是不保存请求的 NullRequestCache
,因为客户端能够重播其最初请求的请求。
Since the user is not authenticated, ExceptionTranslationFilter
initiates Start Authentication.
The configured AuthenticationEntryPoint
is an instance of {security-api-url}org/springframework/security/oauth2/server/resource/authentication/BearerTokenAuthenticationEntryPoint.html[BearerTokenAuthenticationEntryPoint
], which sends a WWW-Authenticate
header.
The RequestCache
is typically a NullRequestCache
that does not save the request, since the client is capable of replaying the requests it originally requested.
当客户端收到 WWW-Authenticate: Bearer
标头时,它便知道应该使用承载令牌重试。下图显示了承载令牌正在被处理的流程:
When a client receives the WWW-Authenticate: Bearer
header, it knows it should retry with a bearer token.
The following image shows the flow for the bearer token being processed:
此图建立在我们的 SecurityFilterChain
图基础上。
The figure builds off our SecurityFilterChain
diagram.
当用户提交他们的持有者令牌时,BearerTokenAuthenticationFilter
会创建一个 BearerTokenAuthenticationToken
,这是一种 Authentication
,通过从 HttpServletRequest
中提取令牌来实现的。
When the user submits their bearer token, the BearerTokenAuthenticationFilter
creates a BearerTokenAuthenticationToken
which is a type of Authentication
by extracting the token from the HttpServletRequest
.
接下来,将 HttpServletRequest
传递给 AuthenticationManagerResolver
,它会选择 AuthenticationManager
。BearerTokenAuthenticationToken
被传递到 AuthenticationManager
以进行身份验证。AuthenticationManager
具体是什么样子取决于您是为 JWT 还是 opaque token 配置的。
Next, the HttpServletRequest
is passed to the AuthenticationManagerResolver
, which selects the AuthenticationManager
. The BearerTokenAuthenticationToken
is passed into the AuthenticationManager
to be authenticated.
The details of what AuthenticationManager
looks like depends on whether you’re configured for JWT or opaque token.
如果身份验证失败,则 Failure
If authentication fails, then Failure
-
The SecurityContextHolder is cleared out.
-
The
AuthenticationEntryPoint
is invoked to trigger the WWW-Authenticate header to be sent again.
如果身份验证成功,则 Success
If authentication is successful, then Success.
-
The Authentication is set on the SecurityContextHolder.
-
The
BearerTokenAuthenticationFilter
invokesFilterChain.doFilter(request,response)
to continue with the rest of the application logic.