一:认证入口:
AbstractAuthenticationProcessingFilter
用于拦截认证请求,它是基于浏览器和 HTTP 认证请求的处理器,可以理解为它就是 Spring Security 认证流程的入口。
整个认证流程如下:
① AbstractAuthenticationProcessingFilter
收集用于认证的用户身份信息(通常是用户名和密码),并基于这些信息构造一个 Authentication
请求对象,AbstractAuthenticationProcessingFilter
只是一个抽象类,查看 Spring Security API 文档 可以看到 Spring Security 提供了几个实现类:
CasAuthenticationFilter
OAuth2LoginAuthenticationFilter
OpenIDAuthenticationFilter
UsernamePasswordAuthenticationFilter
最常使用的应该是 UsernamePasswordAuthenticationFilter
,其它类都应用于特定的场景。
② AbstractAuthenticationProcessingFilter
类将构造的 Authentication
请求对象呈现给 AuthenticationManager
,AbstractAuthenticationProcessingFilter
类有以下方法设置和获取 AuthenticationManager
:
二:Consider a typical web application’s authentication process:
典型的 web 应用程序认证步骤
- You visit the home page, and click on a link.
- A request goes to the server, and the server decides that you’ve asked for a protected resource.
- As you’re not presently authenticated, the server sends back a response indicating that you must authenticate. The response will either be an HTTP response code, or a redirect to a particular web page.
- Depending on the authentication mechanism, your browser will either redirect to the specific web page so that you can fill out the form, or the browser will somehow retrieve your identity (via a BASIC authentication dialogue box, a cookie, a X.509 certificate etc.).
- The browser will send back a response to the server. This will either be an HTTP POST containing the contents of the form that you filled out, or an HTTP header containing your authentication details.
- Next the server will decide whether or not the presented credentials are valid. If they’re valid, the next step will happen. If they’re invalid, usually your browser will be asked to try again (so you return to step two above).
- The original request that you made to cause the authentication process will be retried. Hopefully you’ve authenticated with sufficient granted authorities to access the protected resource. If you have sufficient access, the request will be successful. Otherwise, you’ll receive back an HTTP error code 403, which means "forbidden".
Spring Security has distinct classes responsible for most of the steps described above. The main participants (in the order that they are used) are the ExceptionTranslationFilter
, an AuthenticationEntryPoint
and an "authentication mechanism", which is responsible for calling the AuthenticationManager which we saw in the previous section.
9.4.1 ExceptionTranslationFilter
ExceptionTranslationFilter
is a Spring Security filter that has responsibility for detecting any Spring Security exceptions that are thrown. Such exceptions will generally be thrown by an AbstractSecurityInterceptor
, which is the main provider of authorization services. We will discuss AbstractSecurityInterceptor
in the next section, but for now we just need to know that it produces Java exceptions and knows nothing about HTTP or how to go about authenticating a principal.
ExceptionTranslationFilter 负责响应403(第七步)或者启动AuthenticationEntryPoint
(第三步)
Instead the ExceptionTranslationFilter
offers this service, with specific responsibility for either returning error code 403 (if the principal has been authenticated and therefore simply lacks sufficient access - as per step seven above), or launching an AuthenticationEntryPoint
(if the principal has not been authenticated and therefore we need to go commence step three).
9.4.2 AuthenticationEntryPoint
认证点负责第三步
The AuthenticationEntryPoint
is responsible for step three in the above list. As you can imagine, each web application will have a default authentication strategy (well, this can be configured like nearly everything else in Spring Security, but let’s keep it simple for now). Each major authentication system will have its own AuthenticationEntryPoint
implementation, which typically performs one of the actions described in step 3.
9.4.3 Authentication Mechanism 认证机制
Once your browser submits your authentication credentials (either as an HTTP form post or HTTP header) there needs to be something on the server that "collects" these authentication details.
一旦提交了认证凭证,服务端需要有一些东西来收集这些认证信息
By now we’re at step six in the above list. In Spring Security we have a special name for the function of collecting authentication details from a user agent (usually a web browser), referring to it as the "authentication mechanism".
我们正在上面的列表中的第六步。在Spring Security中,我们为从用户代理(通常是Web浏览器)收集验证信息的功能提供了一个特殊的名称,称之为“验证机制”
Examples are form-base login and Basic authentication. Once the authentication details have been collected from the user agent, an Authentication
"request" object is built and then presented to the AuthenticationManager
.
示例是基于表单的登录和基本身份验证。一旦从用户代理收集了认证详细信息,就构建一个认证“请求”(Authentication
"request")对象,然后将其呈现给AuthenticationManager。
After the authentication mechanism receives back the fully-populated Authentication
object, it will deem the request valid, put the Authentication
into the SecurityContextHolder
, and cause the original request to be retried (step seven above).
认证机制接收到完全填充的认证对象 Authentication
实例(包括权限信息,身份信息,细节信息,但密码通常会被移除)后,认为请求有效,将认证放入SecurityContextHolder,并导致原始请求重试(上面的第七步)
If, on the other hand, the AuthenticationManager
rejected the request, the authentication mechanism will ask the user agent to retry (step two above).
另一方面,如果AuthenticationManager拒绝了请求,认证机制将要求用户代理重试(上面的第二步)
Extending the Secure Object Model
Only developers contemplating an entirely new way of intercepting and authorizing requests would need to use secure objects directly.
只有开发人员想要采用全新的截取和授权请求的方式,才需要直接使用安全对象
For example, it would be possible to build a new secure object to secure calls to a messaging system. Anything that requires security and also provides a way of intercepting a call (like the AOP around advice semantics) is capable of being made into a secure object.
Having said that, most Spring applications will simply use the three currently supported secure object types (AOP Alliance MethodInvocation
, AspectJ JoinPoint
and web request FilterInvocation
) with complete transparency.
话虽如此,大多数Spring应用程序将完全透明地使用目前支持的三种安全对象类型
AbstractSecurityInterceptor 的作用说明:
Abstract class that implements security interception for secure objects.
实现了对安全对象安全拦截的抽象类
The AbstractSecurityInterceptor will ensure the proper startup configuration of the security interceptor. It will also implement the proper handling of secure object invocations, namely:
AbstractSecurityInterceptor 将确保安全拦截器的正确启动配置,它还将实现对安全对象调用的正确处理,即
- Obtain the Authentication object from the SecurityContextHolder.
- Determine if the request relates to a secured or public invocation by looking up the secure object request against the SecurityMetadataSource.
- For an invocation that is secured (there is a list of ConfigAttributes for the secure object invocation):
a. If either the Authentication.isAuthenticated() returns false, or the alwaysReauthenticate is true, authenticate the request against the configured AuthenticationManager. When authenticated, replace the Authentication object on the SecurityContextHolder with the returned value.
b. Authorize the request against the configured AccessDecisionManager.
c. Perform any run-as replacement via the configured RunAsManager.
d. Pass control back to the concrete subclass, which will actually proceed with executing the object. A InterceptorStatusToken is returned so that after the subclass has finished proceeding with execution of the object, its finally clause can ensure the AbstractSecurityInterceptor is re-called and tidies up correctly using finallyInvocation(InterceptorStatusToken).
e. The concrete subclass will re-call the AbstractSecurityInterceptor via the afterInvocation(InterceptorStatusToken, Object) method.
f. If the RunAsManager replaced the Authentication object, return the SecurityContextHolder to the object that existed after the call to AuthenticationManager.
g. If an AfterInvocationManager is defined, invoke the invocation manager and allow it to replace the object due to be returned to the caller. - For an invocation that is public (there are no ConfigAttributes for the secure object invocation):
a. As described above, the concrete subclass will be returned an InterceptorStatusToken which is subsequently re-presented to the AbstractSecurityInterceptor after the secure object has been executed. The AbstractSecurityInterceptor will take no further action when its afterInvocation(InterceptorStatusToken, Object) is called. - Control again returns to the concrete subclass, along with the Object that should be returned to the caller. The subclass will then return that result or exception to the original caller