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 AccessDeniedExceptions. 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