web-infrastructure.xml 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  1. <chapter xmlns="http://docbook.org/ns/docbook" version="5.0" xml:id="web-infrastructure"
  2. xmlns:xlink="http://www.w3.org/1999/xlink">
  3. <info>
  4. <title>Web Application Infrastructure</title>
  5. </info>
  6. <section xml:id="filters">
  7. <title>The Security Filter Chain</title>
  8. <para>Spring Security's web infrastructure is based entirely on standard servlet filters. It
  9. doesn't use servlets or any other servlet-based frameworks (such as Spring MVC) internally, so
  10. it has no strong links to any particular web technology. It deals in
  11. <classname>HttpServletRequest</classname>s and <classname>HttpServletResponse</classname>s
  12. and doesn't care whether the requests come from a browser, a web service client, an
  13. <classname>HttpInvoker</classname> or an AJAX application. </para>
  14. <para> Spring Security maintains a filter chain internally where each of the filters has a
  15. particular responsibility and filters are added or removed from the configuration depending on
  16. which services are required. The ordering of the filters is important as there are
  17. dependencies between them. If you have been using <link xlink:href="#ns-config">namespace
  18. configuration</link>, then the filters are automatically configured for you and you don't
  19. have to define any Spring beans explicitly but here may be times when you want full control
  20. over the security filter chain, either because you are using features which aren't supported
  21. in the namespace, or you are using your own customized versions of classes.</para>
  22. <section xml:id="delegating-filter-proxy">
  23. <title><classname>DelegatingFilterProxy</classname></title>
  24. <para> When using servlet filters, you obviously need to declare them in your
  25. <filename>web.xml</filename>, or they will be ignored by the servlet container. In Spring
  26. Security, the filter classes are also Spring beans defined in the application context and
  27. thus able to take advantage of Spring's rich dependency-injection facilities and lifecycle
  28. interfaces. Spring's <classname>DelegatingFilterProxy</classname> provides the link between
  29. <filename>web.xml</filename> and the application context. </para>
  30. <para>When using <classname>DelegatingFilterProxy</classname>, you will see something like
  31. this in the <filename>web.xml</filename> file: <programlisting><![CDATA[
  32. <filter>
  33. <filter-name>myFilter</filter-name>
  34. <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
  35. </filter>
  36. <filter-mapping>
  37. <filter-name>myFilter</filter-name>
  38. <url-pattern>/*</url-pattern>
  39. </filter-mapping>]]>
  40. </programlisting> Notice that the filter is actually a
  41. <literal>DelegatingFilterProxy</literal>, and not the class that will actually implement
  42. the logic of the filter. What <classname>DelegatingFilterProxy</classname> does is delegate
  43. the <interfacename>Filter</interfacename>'s methods through to a bean which is obtained from
  44. the Spring application context. This enables the bean to benefit from the Spring web
  45. application context lifecycle support and configuration flexibility. The bean must implement
  46. <interfacename>javax.servlet.Filter</interfacename> and it must have the same name as that
  47. in the <literal>filter-name</literal> element. Read the Javadoc for
  48. <classname>DelegatingFilterProxy</classname> for more information</para>
  49. </section>
  50. <section xml:id="filter-chain-proxy">
  51. <title><classname>FilterChainProxy</classname></title>
  52. <para> It should now be clear that you can declare each Spring Security filter bean that you
  53. require in your application context file and add a corresponding
  54. <classname>DelegatingFilterProxy</classname> entry to <filename>web.xml</filename> for
  55. each filter, making sure that they are ordered correctly. This is a cumbersome approach and
  56. clutters up the <filename>web.xml</filename> file quickly if we have a lot of filters. We
  57. would prefer to just add a single entry to <filename>web.xml</filename> and deal entirely
  58. with the application context file for managing our web security beans. This is where Spring
  59. Secuiryt's <classname>FilterChainProxy</classname> comes in. It is wired using a
  60. <literal>DelegatingFilterProxy</literal>, just like in the example above, but with the
  61. <literal>filter-name</literal> set to the bean name <quote>filterChainProxy</quote>. The
  62. filter chain is then declared in the application context with the same bean name. Here's an
  63. example: <programlisting language="xml"><![CDATA[
  64. <bean id="filterChainProxy" class="org.springframework.security.web.FilterChainProxy">
  65. <sec:filter-chain-map path-type="ant">
  66. <sec:filter-chain pattern="/webServices/**" filters="
  67. securityContextPersistenceFilterWithASCFalse,
  68. basicProcessingFilter,
  69. exceptionTranslationFilter,
  70. filterSecurityInterceptor" />
  71. <sec:filter-chain pattern="/**" filters="
  72. securityContextPersistenceFilterWithASCTrue,
  73. authenticationProcessingFilter,
  74. exceptionTranslationFilter,
  75. filterSecurityInterceptor" />
  76. </sec:filter-chain-map>
  77. </bean>
  78. ]]>
  79. </programlisting> The namespace element <literal>filter-chain-map</literal> is
  80. used to set up the security filter chain(s) which are required within the application<footnote>
  81. <para>Note that you'll need to include the security namespace in your application context
  82. XML file in order to use this syntax.</para>
  83. </footnote>. It maps a particular URL pattern to a chain of filters built up from the bean
  84. names specified in the <literal>filters</literal> element. Both regular expressions and Ant
  85. Paths are supported, and the most specific URIs appear first. At runtime the
  86. <classname>FilterChainProxy</classname> will locate the first URI pattern that matches the
  87. current web request and the list of filter beans specified by the <literal>filters</literal>
  88. attribute will be applied to that request. The filters will be invoked in the order they are
  89. defined, so you have complete control over the filter chain which is applied to a particular
  90. URL.</para>
  91. <para>You may have noticed we have declared two
  92. <classname>SecurityContextPersistenceFilter</classname>s in the filter chain
  93. (<literal>ASC</literal> is short for <literal>allowSessionCreation</literal>, a property
  94. of <classname>SecurityContextPersistenceFilter</classname>). As web services will never
  95. present a <literal>jsessionid</literal> on future requests, creating
  96. <literal>HttpSession</literal>s for such user agents would be wasteful. If you had a
  97. high-volume application which required maximum scalability, we recommend you use the
  98. approach shown above. For smaller applications, using a single
  99. <classname>SecurityContextPersistenceFilter</classname> (with its default
  100. <literal>allowSessionCreation</literal> as <literal>true</literal>) would likely be
  101. sufficient.</para>
  102. <para>In relation to lifecycle issues, the <classname>FilterChainProxy</classname> will always
  103. delegate <methodname>init(FilterConfig)</methodname> and <methodname>destroy()</methodname>
  104. methods through to the underlaying <interfacename>Filter</interfacename>s if such methods
  105. are called against <classname>FilterChainProxy</classname> itself. In this case,
  106. <classname>FilterChainProxy</classname> guarantees to only initialize and destroy each
  107. <literal>Filter</literal> bean once, no matter how many times it is declared in the filter
  108. chain(s). You control the overall choice as to whether these methods are called or not via
  109. the <literal>targetFilterLifecycle</literal> initialization parameter of
  110. <literal>DelegatingFilterProxy</literal>. By default this property is
  111. <literal>false</literal> and servlet container lifecycle invocations are not delegated
  112. through <literal>DelegatingFilterProxy</literal>.</para>
  113. <para> When we looked at how to set up web security using <link
  114. xlink:href="#namespace-auto-config">namespace configuration</link>, we used a
  115. <literal>DelegatingFilterProxy</literal> with the name
  116. <quote>springSecurityFilterChain</quote>. You should now be able to see that this is the
  117. name of the <classname>FilterChainProxy</classname> which is created by the namespace. </para>
  118. <section>
  119. <title>Bypassing the Filter Chain</title>
  120. <para> As with the namespace, you can use the attribute <literal>filters = "none"</literal>
  121. as an alternative to supplying a filter bean list. This will omit the request pattern from
  122. the security filter chain entirely. Note that anything matching this path will then have
  123. no authentication or authorization services applied and will be freely accessible. If you
  124. want to make use of the contents of the <classname>SecurityContext</classname> contents
  125. during a request, then it must have passed through the security filter chain. Otherwise
  126. the <classname>SecurityContextHolder</classname> will not have been populated and the
  127. contents will be null.</para>
  128. </section>
  129. </section>
  130. <section>
  131. <title>Filter Ordering</title>
  132. <para>The order that filters are defined in the chain is very important. Irrespective of which
  133. filters you are actually using, the order should be as follows:
  134. <orderedlist>
  135. <listitem>
  136. <para><classname>ChannelProcessingFilter</classname>, because it might need to redirect
  137. to a different protocol</para>
  138. </listitem>
  139. <listitem>
  140. <para><classname>ConcurrentSessionFilter</classname>, because it doesn't use any
  141. <classname>SecurityContextHolder</classname> functionality but needs to update the
  142. <interfacename>SessionRegistry</interfacename> to reflect ongoing requests from the
  143. principal</para>
  144. </listitem>
  145. <listitem>
  146. <para><classname>SecurityContextPersistenceFilter</classname>, so a
  147. <interfacename>SecurityContext</interfacename> can be set up in the
  148. <classname>SecurityContextHolder</classname> at the beginning of a web request, and
  149. any changes to the <interfacename>SecurityContext</interfacename> can be copied to the
  150. <literal>HttpSession</literal> when the web request ends (ready for use with the
  151. next web request)</para>
  152. </listitem>
  153. <listitem>
  154. <para>Authentication processing mechanisms -
  155. <classname>UsernamePasswordAuthenticationProcessingFilter</classname>,
  156. <classname>CasProcessingFilter</classname>,
  157. <classname>BasicProcessingFilter</classname> etc - so that the
  158. <classname>SecurityContextHolder</classname> can be modified to contain a valid
  159. <interfacename>Authentication</interfacename> request token</para>
  160. </listitem>
  161. <listitem>
  162. <para>The <literal>SecurityContextHolderAwareRequestFilter</literal>, if you are using
  163. it to install a Spring Security aware <literal>HttpServletRequestWrapper</literal>
  164. into your servlet container</para>
  165. </listitem>
  166. <listitem>
  167. <para><classname>RememberMeProcessingFilter</classname>, so that if no earlier
  168. authentication processing mechanism updated the
  169. <classname>SecurityContextHolder</classname>, and the request presents a cookie that
  170. enables remember-me services to take place, a suitable remembered
  171. <interfacename>Authentication</interfacename> object will be put there</para>
  172. </listitem>
  173. <listitem>
  174. <para><classname>AnonymousProcessingFilter</classname>, so that if no earlier
  175. authentication processing mechanism updated the
  176. <classname>SecurityContextHolder</classname>, an anonymous
  177. <interfacename>Authentication</interfacename> object will be put there</para>
  178. </listitem>
  179. <listitem>
  180. <para><classname>ExceptionTranslationFilter</classname>, to catch any Spring Security
  181. exceptions so that either an HTTP error response can be returned or an appropriate
  182. <interfacename>AuthenticationEntryPoint</interfacename> can be launched</para>
  183. </listitem>
  184. <listitem>
  185. <para><classname>FilterSecurityInterceptor</classname>, to protect web URIs and raise
  186. exceptions when access is denied</para>
  187. </listitem>
  188. </orderedlist></para>
  189. </section>
  190. <section>
  191. <title>Use with other Filter-Based Frameworks</title>
  192. <para>If you're using some other framework that is also filter-based, then you need to make
  193. sure that the Spring Security filters come first. This enables the
  194. <classname>SecurityContextHolder</classname> to be populated in time for use by the other
  195. filters. Examples are the use of SiteMesh to decorate your web pages or a web framework like
  196. Wicket which uses a filter to handle its requests. </para>
  197. </section>
  198. </section>
  199. <!--
  200. <section xml:id="taglib">
  201. <info>
  202. <title>Tag Libraries</title>
  203. </info>
  204. <para>Spring Security comes bundled with several JSP tag libraries which provide a range of
  205. different services.</para>
  206. <section xml:id="taglib-config">
  207. <info>
  208. <title>Configuration</title>
  209. </info>
  210. <para>All taglib classes are included in the core
  211. <literal>spring-security-taglibs-&lt;version>.jar</literal> file, with the
  212. <literal>security.tld</literal> located in the JAR's <literal>META-INF</literal>
  213. directory. This means for JSP 1.2+ web containers you can simply include the JAR in the
  214. WAR's <literal>WEB-INF/lib</literal> directory and it will be available.</para>
  215. </section>
  216. <section xml:id="taglib-usage">
  217. <info>
  218. <title>Usage</title>
  219. </info>
  220. <para>Now that you've configured the tag libraries, refer to the individual reference guide
  221. sections for details on how to use them. Note that when using the tags, you should include
  222. the taglib reference in your JSP:
  223. <programlisting>
  224. &lt;%@ taglib prefix='security' uri='http://www.springframework.org/security/tags' %&gt;
  225. </programlisting></para>
  226. </section>
  227. </section>
  228. <section xml:id="authentication-taglibs">
  229. <info>
  230. <title>Authentication Tag Libraries</title>
  231. </info>
  232. <para><literal>AuthenticationTag</literal> is used to simply output a property of the current
  233. <interfacename>Authentication</interfacename> object to the web page.</para>
  234. <para>The following JSP fragment illustrates how to use the
  235. <literal>AuthenticationTag</literal>:</para>
  236. <para>
  237. <programlisting>&lt;security:authentication property="principal.username"/&gt;</programlisting>
  238. </para>
  239. <para>This tag would cause the principal's name to be output. Here we are assuming the
  240. <literal>Authentication.getPrincipal()</literal> is a
  241. <interfacename>UserDetails</interfacename> object, which is generally the case when using
  242. one of Spring Security's stadard <classname>AuthenticationProvider</classname>
  243. implementations.</para>
  244. </section>
  245. -->
  246. </chapter>