Particularly in the case of web request URI security, sometimes
it is more convenient to assign configuration attributes against every
possible secure object invocation. Put differently, sometimes it is
nice to say ROLE_SOMETHING
is required by default
and only allow certain exceptions to this rule, such as for login,
logout and home pages of an application. There are also other
situations where anonymous authentication would be desired, such as
when an auditing interceptor queries the
SecurityContextHolder
to identify which principal
was responsible for a given operation. Such classes can be authored
with more robustness if they know the
SecurityContextHolder
always contains an
Authentication
object, and never
null
.
Spring Security provides three classes that together provide an
anonymous authentication feature.
AnonymousAuthenticationToken
is an implementation
of Authentication
, and stores the
GrantedAuthority
[]s which apply to the anonymous
principal. There is a corresponding
AnonymousAuthenticationProvider
, which is chained
into the ProviderManager
so that
AnonymousAuthenticationTokens
are accepted.
Finally, there is an AnonymousProcessingFilter, which is chained after
the normal authentication mechanisms and automatically add an
AnonymousAuthenticationToken
to the
SecurityContextHolder
if there is no existing
Authentication
held there. The definition of the
filter and authentication provider appears as follows:
<bean id="anonymousProcessingFilter" class="org.springframework.security.providers.anonymous.AnonymousProcessingFilter"> <property name="key" value="foobar"/> <property name="userAttribute" value="anonymousUser,ROLE_ANONYMOUS"/> </bean> <bean id="anonymousAuthenticationProvider" class="org.springframework.security.providers.anonymous.AnonymousAuthenticationProvider"> <property name="key" value="foobar"/> </bean>
The key
is shared between the filter and
authentication provider, so that tokens created by the former are
accepted by the latter. The userAttribute
is
expressed in the form of
usernameInTheAuthenticationToken,grantedAuthority[,grantedAuthority]
.
This is the same syntax as used after the equals sign for
InMemoryDaoImpl
's userMap
property.
As explained earlier, the benefit of anonymous authentication is that all URI patterns can have security applied to them. For example:
<bean id="filterInvocationInterceptor" class="org.springframework.security.intercept.web.FilterSecurityInterceptor"> <property name="authenticationManager" ref="authenticationManager"/> <property name="accessDecisionManager" ref="httpRequestAccessDecisionManager"/> <property name="objectDefinitionSource"> <security:filter-invocation-definition-source> <security:intercept-url pattern='/index.jsp' access='ROLE_ANONYMOUS,ROLE_USER'/> <security:intercept-url pattern='/hello.htm' access='ROLE_ANONYMOUS,ROLE_USER'/> <security:intercept-url pattern='/logoff.jsp' access='ROLE_ANONYMOUS,ROLE_USER'/> <security:intercept-url pattern='/login.jsp' access='ROLE_ANONYMOUS,ROLE_USER'/> <security:intercept-url pattern='/**' access='ROLE_USER'/> </security:filter-invocation-definition-source>" + </property> </bean>
Rounding out the anonymous authentication discussion
is the AuthenticationTrustResolver
interface, with
its corresponding AuthenticationTrustResolverImpl
implementation. This interface provides an
isAnonymous(Authentication)
method, which allows
interested classes to take into account this special type of
authentication status. The
ExceptionTranslationFilter
uses this interface in
processing AccessDeniedException
s. If an
AccessDeniedException
is thrown, and the
authentication is of an anonymous type, instead of throwing a 403
(forbidden) response, the filter will instead commence the
AuthenticationEntryPoint
so the principal can
authenticate properly. This is a necessary distinction, otherwise
principals would always be deemed "authenticated" and never be given
an opportunity to login via form, basic, digest or some other normal
authentication mechanism