The main interface responsible for making access-control decisions in Spring Security is the AccessDecisionManager
. It has a decide
method which takes an Authentication
object representing the principal requesting access, a "secure object" (see below) and a list of security metadata attributes which apply for the object (such as a list of roles which are required for access to be granted).
9.5.1 Security and AOP Advice
If you’re familiar with AOP, you’d be aware there are different types of advice available: before, after, throws and around. An around advice is very useful, because an advisor can elect whether or not to proceed with a method invocation, whether or not to modify the response, and whether or not to throw an exception. Spring Security provides an around advice for method invocations as well as web requests. We achieve an around advice for method invocations using Spring’s standard AOP support and we achieve an around advice for web requests using a standard Filter.
9.5.2 Secure Objects and the AbstractSecurityInterceptor
So what is a "secure object" anyway? Spring Security uses the term to refer to any object that can have security (such as an authorization decision) applied to it. The most common examples are method invocations and web requests.
Each supported secure object type has its own interceptor class, which is a subclass of AbstractSecurityInterceptor
. Importantly, by the time the AbstractSecurityInterceptor
is called, the SecurityContextHolder
will contain a valid Authentication
if the principal has been authenticated.
AbstractSecurityInterceptor
provides a consistent workflow for handling secure object requests, typically:
- Look up the "configuration attributes" associated with the present request
查找与当前请求关联的“配置属性”
- Submitting the secure object, current
Authentication
and configuration attributes to theAccessDecisionManager
for an authorization decision将安全对象,当前身份验证和配置属性提交给AccessDecisionManager以进行授权决策 - Optionally change the
Authentication
under which the invocation takes place(可选)更改进行调用的身份验证 - Allow the secure object invocation to proceed (assuming access was granted)
允许安全对象调用继续(假设已授予访问权限)
- Call the
AfterInvocationManager
if configured, once the invocation has returned. If the invocation raised an exception, theAfterInvocationManager
will not be invoked.调用返回后,调用AfterInvocationManager(如果已配置)。如果调用引发异常,则不会调用AfterInvocationManager。
What are Configuration Attributes?
A "configuration attribute" can be thought of as a String that has special meaning to the classes used by AbstractSecurityInterceptor
. They are represented by the interface ConfigAttribute
within the framework. They may be simple role names or have more complex meaning, depending on the how sophisticated the AccessDecisionManager
implementation is. The AbstractSecurityInterceptor
is configured with a SecurityMetadataSource
which it uses to look up the attributes for a secure object. Usually this configuration will be hidden from the user.
<intercept-url pattern='/secure/**' access='ROLE_A,ROLE_B'/>
in the namespace introduction, this is saying that the configuration attributes ROLE_A
and ROLE_B
apply to web requests matching the given pattern. In practice, with the default AccessDecisionManager
configuration, this means that anyone who has a GrantedAuthority
matching either of these two attributes will be allowed access. Strictly speaking though, they are just attributes and the interpretation is dependent on the AccessDecisionManager
implementation. The use of the prefix ROLE_
is a marker to indicate that these attributes are roles and should be consumed by Spring Security’s RoleVoter
. This is only relevant when a voter-based AccessDecisionManager
is in use. We’ll see how the AccessDecisionManager
is implemented in the authorization chapter.RunAsManager
Assuming AccessDecisionManager
decides to allow the request, the AbstractSecurityInterceptor
will normally just proceed with the request. Having said that, on rare occasions users may want to replace the Authentication
inside the SecurityContext
with a different Authentication
, which is handled by the AccessDecisionManager
calling a RunAsManager
. This might be useful in reasonably unusual situations, such as if a services layer method needs to call a remote system and present a different identity. Because Spring Security automatically propagates security identity from one server to another (assuming you’re using a properly-configured RMI or HttpInvoker remoting protocol client), this may be useful.
AfterInvocationManager
Following the secure object invocation proceeding and then returning - which may mean a method invocation completing or a filter chain proceeding - the AbstractSecurityInterceptor
gets one final chance to handle the invocation. At this stage the AbstractSecurityInterceptor
is interested in possibly modifying the return object. We might want this to happen because an authorization decision couldn’t be made "on the way in" to a secure object invocation. Being highly pluggable, AbstractSecurityInterceptor
will pass control to an AfterInvocationManager
to actually modify the object if needed. This class can even entirely replace the object, or throw an exception, or not change it in any way as it chooses. The after-invocation checks will only be executed if the invocation is successful. If an exception occurs, the additional checks will be skipped.
AbstractSecurityInterceptor
and its related objects are shown in Figure 9.1, “Security interceptors and the "secure object" model”
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.