Spring Security 学习笔记(英文原文)
Major building blocks of Spring Security
SecurityContextHolderto provideSecurityContextSecurityContextto hold theAuthenticationAuthenticationto represent the principalGrantedAuthorityto reflect the application-wide permissions granted to a principalUserDetailsto provide the user details information to build an Authentication objectUserDetailsServiceto create aUserDetailswhen passed in aString-based uername.
Authentication in Spring Security
Consider the following scenario:
- A user is prompted to log in with a username and password.
- The system (successfully) verifies that the password is correct for the username.
- The context information for that user is obtained (their list of roles and so on).
- A security context is established for the user
- The user proceeds, potentially to perform some operation which is potentially protected by an access control mechanism which checks the required permissions for the operation against the current security context information.
The first three items constitute the authentication process so we’ll take a look at how these take place within Spring Security.
- The username and password are obtained and combined into an instance of
UsernamePasswordAuthenticationToken(an instance of theAuthenticationinterface, which we saw earlier). - The token is passed to an instance of
AuthenticationManagerfor validation. - The
AuthenticationManagerreturns a fully populatedAuthenticationinstance on successful authentication. - The security context is established by calling
SecurityContextHolder.getContext().setAuthentication(…), passing in the returned authentication object.
From that point on, the user is considered to be authenticated.
Authentication Abstraction in Spring Security for Web Application
Consider a typical web application’s authentication process:
- 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”.
The Main participants are
ExceptionTranslationFilter- a Spring Security filter that has responsibility for detecting any Spring Security exceptions that are thrown (generally be thrown byAbstractSecurityInterceptor). This filter offers the service to translate the exceptions into actual action(url redirection or returning error code 403) or launching anAuthenticationEntryPoint.AuthenticationEntryPoint- responsible for step 3 in the above list.- Authentication Mechansim - responsible for collect authentication details from user (username and password etc.) and buile
Authenticationrequest object then presented toAuthenticationManagerto valid the authentication request and set back toSecurityContextHolder(step 6 - 7 above)
The Security Filter Chain
Filter delegating chain
DelegatingFilterProxy(in web.xml) -> FilterChainProxy(Bean in context) -> each security filter
Security FIlter ordering
The order that security filters are defined in the chain is very import, should be as follows:
ChannelProcessingFilter, because it might need to redirect to a different protocolSecurityContextPersistenceFilter, so aSecurityContextcan be set up in theSecurityContextHolderat the beginning of a web request, and any changes to theSecurityContextcan be copied to theHttpSessionwhen the web request ends (ready for use with the next web request)ConcurrentSessionFilter, because it uses theSecurityContextHolderfunctionality and needs to update theSessionRegistryto refect ongoing requests from the principal.- Authentication processing mechanisms (
UsernamePasswordAuthenticationFilter,CasAuthenticationFilter,BasicAuthenticationFilteretc), so that theSecurityContextHoldercan be modified to contain a validAuthenticationrequest token. - The
SecurityContextHolderAwareRequestFilter, install Spring Security awareHttpServletRequestWrapperinto your servlet container. - The
JaasApiIntegrationFilter, if aJaasAuthenticationTokenis in theSecurityContextHolderthis will process theFilterChainas theSubjectin theJaasAuthenticationToken RememberMeAuhenticationFilter, if no earlier authentication processing mechanism updated theSecurityContextHolder, and the request presents a cookie that enables remember-me services to take place, a suitable rememberedAuthenticationobject will be put hereAnonymousAuthenticationFilter, if no earlier authentication processing mechanism updated theSecurityContextHolder, an anonymousAuthenticationobject will be put here.ExceptionTranslationFilterto catch any Spring Security exceptions so that either an HTTP error response can be returned or an appropriateAuthenticationEntryPointcan be launchedFilterSecurityInterceptorto protect web URIs and raise exceptions when access is denied
The complete order of filters can be found at org.springframework.security.config.annotation.web.builders.FilterComparator
Core Security Filters
There are some key filters which will always be used in Spring Security web application.
FilterSecurityInterceptor
- Responsible for handling the security of HTTP resources.
- has a reference to an
AuthenticationManagerand aAccessDecisionManager - supplied with configuration attributes (or SecurityMetadataSource) that apply to different HTTP URL request.
- extends
AbstractSecurityInterceptor
ExceptionTranslationFilter
- sits above
FilterSecurityInterceptor - doesn’t do any actual security enforcement itself
- handles exceptions thrown by the security interceptors and provide suitable HTTP response
AuthenticationEntryPointwill be called if the user requests a secure HTTP resource but they are not authenticated. (AuthenticationExceptionwill be thrown by a security interceptor futher down the call stace, triggerint thecommencemethod on the entry point.)AccessDeniedHandlerwill be called if the user authenticated but don’t have enough permissions to access the resources. (AccessDeniedExceptionwill be thrown by a security interceptor futher down the call stack)- Also responsible for saving the current request before
AuthenticationEntryPointis invoked and restoring after the user has authenticated. (SavedRequests andRequestCache)
SecurityContextPersistenceFilter
- Responsible for storage of the
SecurityContextcontents between HTTP requests - Responsible for clearing the
SecurityContextHolderwhen a request is completed. - v3.0 onward,
SecurityContextRepositoryis used for different storage strategy.
Authorization in Spring Security
The main interface responsible for making access-control decisions is AccessDecisionManager, it decides the principal represented by an Authentication object can or can not access the “secure object” using a list of security metadata attributes which apply for the object.
Secure Object
“secure object” refers to any object that can have security (such as an authorization decision) applied to it, for example: method invocations and web requests.
workflow
Each supported secure object type has its own implementation of AbstractSecurityInterceptor, but the workflow for handling secure object requests is consistent:
- Look up the “configuration attributes” associated with the present request
- Submitting the secure object, current
Authenticationand configuration attributes to theAccessDecisionManagerfor an authorization decision - Optionally change the
Authenticationunder which the invocation takes place - Allow the secure object invocation to proceed (assuming access was granted)
- Call the
AfterInvocationManagerif configured, once the invocation has returned. If the invocation raised an exception, theAfterInvocationManagerwill not be invoked.
configuration attributes
Can be thought of as a String that has special meaning to the classes used by AbstractSecurityInterceptor, represented by the interface ConfigAttribute within the framework. May be simple role names or have more complex meaning, depending on the implementation of AccessDecisionManager.
AbstractSecurityInterceptor uses SecurityMetadataSource to look up the attributes for a secure object. Usually configuration attributes will be entered as annotations on secured methods or as access attributes on secured URLs. For exmple, <intercept-url pattern='/secure/**' access='ROLE_A,ROLE_B' /> is saying that the configuration attributes ROLE_A and ROLE_B apply to web requests matching the given pattern.
Authorities
All Authentication implementations store a list of GrantedAuthority objects, represent the authorities that have been granted to the principal, and are inserted by AuthenticationManager and are later read by AccessDecisionManager when making authorization decisions.
AccessDecisionManager
decideall the authorization decisions for the “secured object”. ThrowAccessDeniedExceptionif access is denied.supports(ConfigAttribute)is used byAbstractSecurityInterceptorat startup time to determine if theAccessDecisionManagercan process the passedConfigAttribute.supports(Class)is used by a security interceptor implementation to ensure theAccessDecisionManagersupports the type of secure object.AccessDecisionManagerdelegates authorization decisions toAccessDecisionVoters
Voting-Based Implementations
A series of AccessDecisionVoter implementations are polled on authorization decision, then AccessDecisionManager decides whether or not to throw an AccessDeniedException based on its assessment of the votes.
Concrete implementations of AccessDecisionVoter returns int result, possible values are: (All are reflected in the AccessDecisionVoter static fields)
ACCESS_ABSTAIN(a voting implementation has no opinion on an authorization decision),ACCESS_DENIED,ACCESS_GRANTED
There are 3 concrete AccessDecisionManagers that tally the votes:
AffirmativeBased- will grant access if one or moreACCESS_GRANTEDvotes were received.ConsensusBased- will grant or deny access based on the consensus of non-abstain votesUnanimousBased- expects unanimousACCESS_GRANTEDvotes in order to grant access, ignoring abstains. It will deny access if there is anyACCESS_DENIEDvote ( Properties are provided to controls the behaviour if all votes are abstain or in the event of an equality of votes. )
Voters
RoleVoter- most commonly used, vote againstROLE_prefixedConfigAttributeAuthenticatedVoter- used to differentiate between anonymous, fully-authenticated and remember-me authenticated users.- Custom voters - you can implement a custom
AccessDecisionVoter
- 完 -
