Spring Security uses the term "secure object" 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.
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.
For those not familiar with AOP, the key point to understand is that Spring Security can help you protect method invocations as well as web requests. Most people are interested in securing method invocations on their services layer. This is because the services layer is where most business logic resides in current-generation J2EE applications (for clarification, the author disapproves of this design and instead advocates properly encapsulated domain objects together with the DTO, assembly, facade and transparent persistence patterns, but as use of anemic domain objects is the present mainstream approach, we'll talk about it here). If you just need to secure method invocations to the services layer, Spring's standard AOP (otherwise known as AOP Alliance) will be adequate. If you need to secure domain objects directly, you will likely find that AspectJ is worth considering.
You can elect to perform method authorization using AspectJ or Spring AOP, or you can elect to perform web request authorization using filters. You can use zero, one, two or three of these approaches together. The mainstream usage is to perform some web request authorization, coupled with some Spring AOP method invocation authorization on the services layer.
Each secure object type supported by Spring Security has its own 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 the AccessDecisionManager
for
an authorization decision
Optionally change the Authentication
under which the invocation
takes place
Allow the secure object to proceed (assuming access was granted)
Call the AfterInvocationManager
if configured, once the invocation
has returned.
A "configuration attribute" can be thought of as a String that has special meaning to the classes used by
AbstractSecurityInterceptor
. 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 an ObjectDefinitionSource
which
it uses to look up the attributes for a secure object. Usually this configuration will be hidden from the user. Configuration
attributes will be entered as annotations on secured methods, or as access attributes on secured URLs (using the
namespace <intercept-url>
syntax).
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.
Following the secure object 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.
AbstractSecurityInterceptor
and its related objects
are shown in Figure 5.1, “The key "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.