123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138 |
- <chapter xmlns="http://docbook.org/ns/docbook" version="5.0" xml:id="anonymous"
- xmlns:xlink="http://www.w3.org/1999/xlink">
- <info>
- <title>Anonymous Authentication</title>
- </info>
- <section xml:id="anonymous-overview">
- <info>
- <title>Overview</title>
- </info>
- <para>It's generally considered good security practice to adopt a
- <quote>deny-by-default</quote> where you explicitly specify what is allowed and disallow
- everything else. Defining what is accessible to unauthenticated users is a similar
- situation, particularly for web applications. Many sites require that users must be
- authenticated for anything other than a few URLs (for example the home and login pages).
- In this case it is easiest to define access configuration attributes for these specific
- URLs rather than have for every secured resource. Put differently, sometimes it is nice
- to say <literal>ROLE_SOMETHING</literal> is required by default and only allow certain
- exceptions to this rule, such as for login, logout and home pages of an application. You
- could also omit these pages from the filter chain entirely, thus bypassing the access
- control checks, but this may be undesirable for other reasons, particularly if the pages
- behave differently for authenticated users.</para>
- <para>This is what we mean by anonymous authentication. Note that there is no real
- conceptual difference between a user who is <quote>anonymously authenticated</quote> and
- an unauthenticated user. Spring Security's anonymous authentication just gives you a
- more convenient way to configure your access-control attributes. Calls to servlet API
- calls such as <methodname>getCallerPrincipal</methodname>, for example, will still
- return null even though there is actually an anonymous authentication object in the
- <classname>SecurityContextHolder</classname>.</para>
- <para>There are other situations where anonymous authentication is useful, such as when an
- auditing interceptor queries the <classname>SecurityContextHolder</classname> to
- identify which principal was responsible for a given operation. Classes can be authored
- more robustly if they know the <classname>SecurityContextHolder</classname> always
- contains an <interfacename>Authentication</interfacename> object, and never
- <literal>null</literal>.</para>
- </section>
- <section xml:id="anonymous-config">
- <info>
- <title>Configuration</title>
- </info>
- <para>Anonymous authentication support is provided automatically when using the HTTP
- configuration Spring Security 3.0 and can be customized (or disabled) using the
- <literal><anonymous></literal> element. You don't need to configure the beans
- described here unless you are using traditional bean configuration.</para>
- <para>Three classes that together provide the anonymous authentication feature.
- <literal>AnonymousAuthenticationToken</literal> is an implementation of
- <interfacename>Authentication</interfacename>, and stores the
- <interfacename>GrantedAuthority</interfacename>s which apply to the anonymous principal.
- There is a corresponding <literal>AnonymousAuthenticationProvider</literal>, which is
- chained into the <literal>ProviderManager</literal> so that
- <literal>AnonymousAuthenticationToken</literal>s are accepted. Finally, there is an
- <classname>AnonymousAuthenticationFilter</classname>, which is chained after the normal
- authentication mechanisms and automatically adds an
- <literal>AnonymousAuthenticationToken</literal> to the
- <classname>SecurityContextHolder</classname> if there is no existing
- <interfacename>Authentication</interfacename> held there. The definition of the filter
- and authentication provider appears as follows:</para>
- <para> <programlisting>
- <![CDATA[
- <bean id="anonymousAuthFilter"
- class="org.springframework.security.web.authentication.AnonymousAuthenticationFilter">
- <property name="key" value="foobar"/>
- <property name="userAttribute" value="anonymousUser,ROLE_ANONYMOUS"/>
- </bean>
- <bean id="anonymousAuthenticationProvider"
- class="org.springframework.security.authentication.AnonymousAuthenticationProvider">
- <property name="key" value="foobar"/>
- </bean>]]>
- </programlisting> </para>
- <para>The <literal>key</literal> is shared between the filter and authentication provider,
- so that tokens created by the former are accepted by the latter<footnote>
- <para>The use of the <literal>key</literal> property should not be regarded as providing
- any real security here. It is merely a book-keeping exercise. If you are sharing a
- <classname>ProviderManager</classname> which contains an
- <classname>AnonymousAuthenticationProvider</classname> in a scenario where it is
- possible for an authenticating client to construct the
- <interfacename>Authentication</interfacename> object (such as with RMI invocations),
- then a malicious client could submit an
- <classname>AnonymousAuthenticationToken</classname> which it had created itself
- (with chosen username and authority list). If the <literal>key</literal> is
- guessable or can be found out, then the token would be accepted by the anonymous
- provider. This isn't a problem with normal usage but if you are using RMI you would
- be best to use a customized <classname>ProviderManager</classname> which omits the
- anonymous provider rather than sharing the one you use for your HTTP authentication
- mechanisms.</para>
- </footnote>. The <literal>userAttribute</literal> is expressed in the form of
- <literal>usernameInTheAuthenticationToken,grantedAuthority[,grantedAuthority]</literal>.
- This is the same syntax as used after the equals sign for
- <literal>InMemoryDaoImpl</literal>'s <literal>userMap</literal> property.</para>
- <para>As explained earlier, the benefit of anonymous authentication is that all URI patterns
- can have security applied to them. For example:</para>
- <para> <programlisting>
- <![CDATA[
- <bean id="filterSecurityInterceptor"
- class="org.springframework.security.web.access.intercept.FilterSecurityInterceptor">
- <property name="authenticationManager" ref="authenticationManager"/>
- <property name="accessDecisionManager" ref="httpRequestAccessDecisionManager"/>
- <property name="securityMetadata">
- <security:filter-security-metadata-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-security-metadata-source>" +
- </property>
- </bean>]]>
- </programlisting> </para>
- </section>
- <section xml:id="anonymous-auth-trust-resolver">
- <title><interfacename>AuthenticationTrustResolver</interfacename></title>
- <para> Rounding out the anonymous authentication discussion is the
- <interfacename>AuthenticationTrustResolver</interfacename> interface, with its
- corresponding <literal>AuthenticationTrustResolverImpl</literal> implementation. This
- interface provides an <literal>isAnonymous(Authentication)</literal> method, which
- allows interested classes to take into account this special type of authentication
- status. The <classname>ExceptionTranslationFilter</classname> uses this interface in
- processing <literal>AccessDeniedException</literal>s. If an
- <literal>AccessDeniedException</literal> is thrown, and the authentication is of an
- anonymous type, instead of throwing a 403 (forbidden) response, the filter will instead
- commence the <interfacename>AuthenticationEntryPoint</interfacename> so the principal
- can authenticate properly. This is a necessary distinction, otherwise principals would
- always be deemed <quote>authenticated</quote> and never be given an opportunity to login
- via form, basic, digest or some other normal authentication mechanism. </para>
- <para> You will often see the <literal>ROLE_ANONYMOUS</literal> attribute in the above
- interceptor configuration replaced with <literal>IS_AUTHENTICATED_ANONYMOUSLY</literal>,
- which is effectively the same thing when defining access controls. This is an example of
- the use of the <classname>AuthenticatedVoter</classname> which we will see in the <link
- xlink:href="#authz-authenticated-voter">authorization chapter</link>. It uses an
- <interfacename>AuthenticationTrustResolver</interfacename> to process this particular
- configuration attribute and grant access to anonymous users. The
- <classname>AuthenticatedVoter</classname> approach is more powerful, since it allows you
- to differentiate between anonymous, remember-me and fully-authenticated users. If you
- don't need this functionality though, then you can stick with
- <literal>ROLE_ANONYMOUS</literal>, which will be processed by Spring Security's standard
- <classname>RoleVoter</classname>. </para>
- </section>
- </chapter>
|