| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342 |
- <chapter xmlns="http://docbook.org/ns/docbook" version="5.0" xml:id="supporting-infrastructure" xmlns:xlink="http://www.w3.org/1999/xlink">
-
- <info><title>Supporting Infrastructure</title></info>
-
- <para>This chapter introduces some of the supplementary and supporting
- infrastructure used by Spring Security. If a capability is not directly
- related to security, yet included in the Spring Security project, we
- will discuss it in this chapter.</para>
- <section xml:id="localization">
- <title>Localization</title>
- <para>Spring Security supports localization of exception messages that
- end users are likely to see. If your application is designed for
- English users, you don't need to do anything as by default all
- Security Security messages are in English. If you need to support
- other locales, everything you need to know is contained in this
- section.</para>
- <para>All exception messages can be localized, including messages
- related to authentication failures and access being denied
- (authorization failures). Exceptions and logging that is focused on
- developers or system deployers (including incorrect attributes,
- interface contract violations, using incorrect constructors, startup
- time validation, debug-level logging) etc are not localized and
- instead are hard-coded in English within Spring Security's
- code.</para>
- <para>Shipping in the <literal>spring-security-core-xx.jar</literal> you
- will find an <literal>org.springframework.security</literal> package
- that in turn contains a <literal>messages.properties</literal> file.
- This should be referred to by your
- <literal>ApplicationContext</literal>, as Spring Security classes
- implement Spring's <literal>MessageSourceAware</literal> interface and
- expect the message resolver to be dependency injected at application
- context startup time. Usually all you need to do is register a bean
- inside your application context to refer to the messages. An example
- is shown below:</para>
- <para><programlisting><![CDATA[
- <bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
- <property name="basename" value="org/springframework/security/messages"/>
- </bean>
- ]]></programlisting></para>
- <para>The <literal>messages.properties</literal> is named in
- accordance with standard resource bundles and represents the default
- language supported by Spring Security messages. This default file is
- in English. If you do not register a message source, Spring Security
- will still work correctly and fallback to hard-coded English versions
- of the messages.</para>
- <para>If you wish to customize the
- <literal>messages.properties</literal> file, or support other
- languages, you should copy the file, rename it accordingly, and
- register it inside the above bean definition. There are not a large
- number of message keys inside this file, so localization should not be
- considered a major initiative. If you do perform localization of this
- file, please consider sharing your work with the community by logging
- a JIRA task and attaching your appropriately-named localized version
- of <literal>messages.properties</literal>.</para>
- <para>Rounding out the discussion on localization is the Spring
- <literal>ThreadLocal</literal> known as
- <literal>org.springframework.context.i18n.LocaleContextHolder</literal>.
- You should set the <literal>LocaleContextHolder</literal> to represent
- the preferred <literal>Locale</literal> of each user. Spring Security
- will attempt to locate a message from the message source using the
- <literal>Locale</literal> obtained from this
- <literal>ThreadLocal</literal>. Please refer to Spring documentation
- for further details on using <literal>LocaleContextHolder</literal>
- and the helper classes that can automatically set it for you (eg
- <literal>AcceptHeaderLocaleResolver</literal>,
- <literal>CookieLocaleResolver</literal>,
- <literal>FixedLocaleResolver</literal>,
- <literal>SessionLocaleResolver</literal> etc)</para>
- </section>
- <section xml:id="filters">
- <info><title>Filters</title></info>
- <para>Spring Security uses many filters, as referred to throughout the
- remainder of this reference guide. If you are using <link xlink:href="#ns-config">namespace configuration</link>,
- then the you don't usually have to declare the filter beans explicitly. There may be times when you want full control
- over the security filter chain, either because you are using features which aren't supported in the namespace, or you
- are using your own customized versions of classes.</para>
- <para>In this case, you have a choice in how these filters are added to your web application, in that you can use either
- Spring's <literal>DelegatingFilterProxy</literal> or
- <classname>FilterChainProxy</classname>. We'll look at both below.</para>
-
- <para>When using <literal>DelegatingFilterProxy</literal>, you will see
- something like this in the web.xml file:
-
- <programlisting>
- <filter>
- <filter-name>myFilter</filter-name>
- <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
- </filter>
- <filter-mapping>
- <filter-name>myFilter</filter-name>
- <url-pattern>/*</url-pattern>
- </filter-mapping>
- </programlisting>
-
- Notice that the filter is actually a <literal>DelegatingFilterProxy</literal>,
- and not the filter that will actually implement the logic of the filter. What
- <literal>DelegatingFilterProxy</literal> does is delegate the
- <literal>Filter</literal>'s methods through to a bean which is
- obtained from the Spring application context. This enables the bean to
- benefit from the Spring web application context lifecycle support and
- configuration flexibility. The bean must implement
- <literal>javax.servlet.Filter</literal> and it must have the same name as that in
- the <literal>filter-name</literal> element.</para>
- <para>There is a lifecycle issue to consider when hosting
- <literal>Filter</literal>s in an IoC container instead of a servlet
- container. Specifically, which container should be responsible for
- calling the <literal>Filter</literal>'s "startup" and "shutdown"
- methods? It is noted that the order of initialization and destruction
- of a <literal>Filter</literal> can vary by servlet container, and this
- can cause problems if one <literal>Filter</literal> depends on
- configuration settings established by an earlier initialized
- <literal>Filter</literal>. The Spring IoC container on the other hand
- has more comprehensive lifecycle/IoC interfaces (such as
- <literal>InitializingBean</literal>,
- <literal>DisposableBean</literal>, <literal>BeanNameAware</literal>,
- <literal>ApplicationContextAware</literal> and many others) as well as
- a well-understood interface contract, predictable method invocation
- ordering, autowiring support, and even options to avoid implementing
- Spring interfaces (eg the <literal>destroy-method</literal> attribute
- in Spring XML). For this reason we recommend the use of Spring
- lifecycle services instead of servlet container lifecycle services
- wherever possible. Read the Javadoc for <classname>DelegatingFilterProxy</classname>
- for more information</para>
- <para>Rather than using <literal>DelegatingFilterProxy</literal>, we
- strongly recommend that you use <classname>FilterChainProxy</classname> instead.
- Whilst <literal>DelegatingFilterProxy</literal> is a very useful class,
- the problem is that the number of lines of code required for
- <literal><filter></literal> and
- <literal><filter-mapping></literal> entries in
- <literal>web.xml</literal> explodes when using more than a few
- filters. To overcome this issue, Spring Security provides a
- <classname>FilterChainProxy</classname> class. It is wired using a
- <literal>DelegatingFilterProxy</literal> (just like in the example above),
- but the target class is
- <literal>org.springframework.security.util.FilterChainProxy</literal>.
- The filter chain is then declared in the application context, using
- code such as this:</para>
- <para><programlisting><![CDATA[
- <bean id="filterChainProxy" class="org.springframework.security.util.FilterChainProxy">
- <sec:filter-chain-map path-type="ant">
- <sec:filter-chain pattern="/webServices/**"
- filters="httpSessionContextIntegrationFilterWithASCFalse,basicProcessingFilter,exceptionTranslationFilter,filterSecurityInterceptor"/>
- <sec:filter-chain pattern="/**"
- filters="httpSessionContextIntegrationFilterWithASCTrue,authenticationProcessingFilter,exceptionTranslationFilter,filterSecurityInterceptor"/>
- </sec:filter-chain-map>
- </bean>
- ]]>
- </programlisting></para>
- <para>You may notice similarities with the way
- <classname>FilterSecurityInterceptor</classname> is declared. Both regular
- expressions and Ant Paths are supported, and the most specific URIs
- appear first. At runtime the <classname>FilterChainProxy</classname> will
- locate the first URI pattern that matches the current web request and the list
- of filter beans specified by the <literal>filters</literal> attribute
- will be applied to that request. The filters will be invoked in the order
- they are defined, so you have complete control over the filter chain
- which is applied to a particular URL.</para>
- <para>You may have noticed we have declared two
- <classname>HttpSessionContextIntegrationFilter</classname>s in the filter
- chain (<literal>ASC</literal> is short for
- <literal>allowSessionCreation</literal>, a property of
- <classname>HttpSessionContextIntegrationFilter</classname>). As web
- services will never present a <literal>jsessionid</literal> on future
- requests, creating <literal>HttpSession</literal>s for such user
- agents would be wasteful. If you had a high-volume application which
- required maximum scalability, we recommend you use the approach shown
- above. For smaller applications, using a single
- <classname>HttpSessionContextIntegrationFilter</classname> (with its
- default <literal>allowSessionCreation</literal> as
- <literal>true</literal>) would likely be sufficient.</para>
- <para>In relation to lifecycle issues, the
- <classname>FilterChainProxy</classname> will always delegate
- <literal>init(FilterConfig)</literal> and <literal>destroy()</literal>
- methods through to the underlaying <literal>Filter</literal>s if such
- methods are called against <classname>FilterChainProxy</classname> itself.
- In this case, <classname>FilterChainProxy</classname> guarantees to only
- initialize and destroy each <literal>Filter</literal> once,
- irrespective of how many times it is declared by the
- <interfacename>FilterInvocationDefinitionSource</interfacename>. You control the
- overall choice as to whether these methods are called or not via the
- <literal>targetFilterLifecycle</literal> initialization parameter of the
- <literal>DelegatingFilterProxy</literal> that proxies
- <literal>DelegatingFilterProxy</literal>. As discussed above, by default
- any servlet container lifecycle invocations are not delegated through
- to <literal>DelegatingFilterProxy</literal>.</para>
- <para>You can use the attribute <literal>filters = "none"</literal>
- in the same way that you do when using <link xlink:href="#namespace-auto-config">namespace configuration</link>
- to build the <classname>FilterChainProxy</classname>. This will omit the
- request pattern from the security filter chain entirely.
- Note that anything matching this path will then have
- no authentication or authorization services applied and will be freely
- accessible.</para>
- <para>The order that filters are defined in <literal>web.xml</literal>
- is very important. Irrespective of which filters you are actually
- using, the order of the <literal><filter-mapping></literal>s
- should be as follows:</para>
- <orderedlist inheritnum="ignore" continuation="restarts">
- <listitem>
- <para><literal>ChannelProcessingFilter</literal>, because it might
- need to redirect to a different protocol</para>
- </listitem>
- <listitem>
- <para><literal>ConcurrentSessionFilter</literal>, because it
- doesn't use any <classname>SecurityContextHolder</classname>
- functionality but needs to update the
- <interfacename>SessionRegistry</interfacename> to reflect ongoing requests
- from the principal</para>
- </listitem>
- <listitem>
- <para><classname>HttpSessionContextIntegrationFilter</classname>, so a
- <interfacename>SecurityContext</interfacename> can be setup in the
- <classname>SecurityContextHolder</classname> at the beginning of a web
- request, and any changes to the <interfacename>SecurityContext</interfacename>
- can be copied to the <literal>HttpSession</literal> when the web
- request ends (ready for use with the next web request)</para>
- </listitem>
- <listitem>
- <para>Authentication processing mechanisms -
- <literal>AuthenticationProcessingFilter</literal>,
- <literal>CasProcessingFilter</literal>,
- <literal>BasicProcessingFilter, HttpRequestIntegrationFilter,
- JbossIntegrationFilter</literal> etc - so that the
- <classname>SecurityContextHolder</classname> can be modified to
- contain a valid <interfacename>Authentication</interfacename> request
- token</para>
- </listitem>
- <listitem>
- <para>The
- <literal>SecurityContextHolderAwareRequestFilter</literal>, if you
- are using it to install a Spring Security aware
- <literal>HttpServletRequestWrapper</literal> into your servlet
- container</para>
- </listitem>
- <listitem>
- <para><classname>RememberMeProcessingFilter</classname>, so that if no
- earlier authentication processing mechanism updated the
- <classname>SecurityContextHolder</classname>, and the request presents
- a cookie that enables remember-me services to take place, a
- suitable remembered
- <interfacename>Authentication</interfacename> object will
- be put there</para>
- </listitem>
- <listitem>
- <para><literal>AnonymousProcessingFilter</literal>, so that if no
- earlier authentication processing mechanism updated the
- <classname>SecurityContextHolder</classname>, an anonymous
- <interfacename>Authentication</interfacename> object will be put there</para>
- </listitem>
- <listitem>
- <para><classname>ExceptionTranslationFilter</classname>, to catch any
- Spring Security exceptions so that either an HTTP error response
- can be returned or an appropriate
- <interfacename>AuthenticationEntryPoint</interfacename> can be launched</para>
- </listitem>
- <listitem>
- <para><classname>FilterSecurityInterceptor</classname>, to protect web
- URIs</para>
- </listitem>
- </orderedlist>
- <para>All of the above filters use
- <literal>DelegatingFilterProxy</literal> or
- <classname>FilterChainProxy</classname>. It is recommended that a single
- <literal>DelegatingFilterProxy</literal> proxy through to a single
- <classname>FilterChainProxy</classname> for each application, with that
- <classname>FilterChainProxy</classname> defining all of Spring Security
- filters.</para>
- <para>If you're using SiteMesh, ensure Spring Security filters execute
- before the SiteMesh filters are called. This enables the
- <classname>SecurityContextHolder</classname> to be populated in time for
- use by SiteMesh decorators</para>
- </section>
-
- <section xml:id="taglib">
- <info><title>Tag Libraries</title></info>
- <para>Spring Security comes bundled with several JSP tag libraries which provide a range of different
- services.</para>
-
- <section xml:id="taglib-config">
- <info><title>Configuration</title></info>
- <para>All taglib classes are included in the core
- <literal>spring-security-xx.jar</literal> file, with the
- <literal>security.tld</literal> located in the JAR's
- <literal>META-INF</literal> directory. This means for JSP 1.2+ web
- containers you can simply include the JAR in the WAR's
- <literal>WEB-INF/lib</literal> directory and it will be available. If
- you're using a JSP 1.1 container, you'll need to declare the JSP
- taglib in your <literal>web.xml file</literal>, and include
- <literal>security.tld</literal> in the <literal>WEB-INF/lib</literal>
- directory. The following fragment is added to
- <literal>web.xml</literal>:
- <programlisting><![CDATA[
- <taglib>
- <taglib-uri>http://www.springframework.org/security/tags</taglib-uri>
- <taglib-location>/WEB-INF/security.tld</taglib-location>
- </taglib>
- ]]></programlisting></para>
- </section>
-
- <section xml:id="taglib-usage">
- <info><title>Usage</title></info>
- <para>Now that you've configured the tag libraries, refer to the
- individual reference guide sections for details on how to use them.
- Note that when using the tags, you should include the taglib reference
- in your JSP:
- <programlisting>
- <%@ taglib prefix='security' uri='http://www.springframework.org/security/tags' %>
-
- </programlisting></para>
- </section>
- </section>
- </chapter>
|