namespace-config.xml 53 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <chapter xmlns="http://docbook.org/ns/docbook" version="5.0" xml:id="ns-config"
  3. xmlns:xlink="http://www.w3.org/1999/xlink">
  4. <info>
  5. <title>Security Namespace Configuration</title>
  6. </info>
  7. <section>
  8. <title>Introduction</title>
  9. <para> Namespace configuration has been available since version 2.0 of the Spring framework. It
  10. allows you to supplement the traditional Spring beans application context syntax with elements
  11. from additional XML schema. You can find more information in the Spring <link
  12. xlink:href="http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/htmlsingle/spring-framework-reference.htm"
  13. > Reference Documentation</link>. A namespace element can be used simply to allow a more
  14. concise way of configuring an individual bean or, more powerfully, to define an alternative
  15. configuration syntax which more closely matches the problem domain and hides the underlying
  16. complexity from the user. A simple element may conceal the fact that multiple beans and
  17. processing steps are being added to the application context. For example, adding the following
  18. element from the security namespace to an application context will start up an embedded LDAP
  19. server for testing use within the application: <programlisting language="xml"><![CDATA[
  20. <security:ldap-server />
  21. ]]></programlisting> This is much simpler than wiring up the equivalent Apache Directory Server
  22. beans. The most common alternative configuration requirements are supported by attributes on
  23. the <literal>ldap-server</literal> element and the user is isolated from worrying about which
  24. beans they need to create and what the bean property names are. <footnote><para>You can find
  25. out more about the use of the <literal>ldap-server</literal> element in the chapter on
  26. <link xlink:href="#ldap">LDAP</link>.</para></footnote>. Use of a good XML editor while
  27. editing the application context file should provide information on the attributes and elements
  28. that are available. We would recommend that you try out the <link
  29. xlink:href="http://www.springsource.com/products/sts">SpringSource Tool Suite</link> as it
  30. has special features for working with standard Spring namespaces. </para>
  31. <para> To start using the security namespace in your application context, you first need to make
  32. sure that the <literal>spring-security-config</literal> jar is on your classpath. Then all you need to do is
  33. add the schema declaration to your application context file: <programlisting language="xml">
  34. <![CDATA[
  35. <beans xmlns="http://www.springframework.org/schema/beans"
  36. xmlns:security="http://www.springframework.org/schema/security"
  37. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  38. xsi:schemaLocation="http://www.springframework.org/schema/beans
  39. http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
  40. http://www.springframework.org/schema/security
  41. http://www.springframework.org/schema/security/spring-security-3.0.3.xsd">
  42. ...
  43. </beans>
  44. ]]></programlisting> In many of the examples you will see (and in the sample) applications, we
  45. will often use "security" as the default namespace rather than "beans", which means we can
  46. omit the prefix on all the security namespace elements, making the content easier to read. You
  47. may also want to do this if you have your application context divided up into separate files
  48. and have most of your security configuration in one of them. Your security application context
  49. file would then start like this <programlisting language="xml"><![CDATA[
  50. <beans:beans xmlns="http://www.springframework.org/schema/security"
  51. xmlns:beans="http://www.springframework.org/schema/beans"
  52. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  53. xsi:schemaLocation="http://www.springframework.org/schema/beans
  54. http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
  55. http://www.springframework.org/schema/security
  56. http://www.springframework.org/schema/security/spring-security-3.0.3.xsd">
  57. ...
  58. </beans:beans>
  59. ]]></programlisting> We'll assume this syntax is being used from now on in this chapter. </para>
  60. <section>
  61. <title>Design of the Namespace</title>
  62. <para> The namespace is designed to capture the most common uses of the framework and provide
  63. a simplified and concise syntax for enabling them within an application. The design is based
  64. around the large-scale dependencies within the framework, and can be divided up into the
  65. following areas: <itemizedlist><listitem><para>
  66. <emphasis>Web/HTTP Security</emphasis> - the most complex part. Sets up the filters
  67. and related service beans used to apply the framework authentication mechanisms, to
  68. secure URLs, render login and error pages and much
  69. more.</para></listitem><listitem><para>
  70. <emphasis>Business Object (Method) Security</emphasis> - options for securing the
  71. service layer.</para></listitem><listitem><para>
  72. <emphasis>AuthenticationManager</emphasis> - handles authentication requests from
  73. other parts of the framework.</para></listitem><listitem><para>
  74. <emphasis>AccessDecisionManager</emphasis> - provides access decisions for web and
  75. method security. A default one will be registered, but you can also choose to use a
  76. custom one, declared using normal Spring bean
  77. syntax.</para></listitem><listitem><para>
  78. <emphasis>AuthenticationProvider</emphasis>s - mechanisms against which the
  79. authentication manager authenticates users. The namespace provides supports for
  80. several standard options and also a means of adding custom beans declared using a
  81. traditional syntax. </para></listitem><listitem><para>
  82. <emphasis>UserDetailsService</emphasis> - closely related to authentication providers,
  83. but often also required by other beans.</para></listitem>
  84. <!-- todo: diagram and link to other sections which describe the interfaces -->
  85. </itemizedlist></para>
  86. <para>We'll see how to configure these in the following sections.</para>
  87. </section>
  88. </section>
  89. <section xml:id="ns-getting-started">
  90. <title>Getting Started with Security Namespace Configuration</title>
  91. <para> In this section, we'll look at how you can build up a namespace configuration to use some
  92. of the main features of the framework. Let's assume you initially want to get up and running
  93. as quickly as possible and add authentication support and access control to an existing web
  94. application, with a few test logins. Then we'll look at how to change over to authenticating
  95. against a database or other security repository. In later sections we'll introduce more
  96. advanced namespace configuration options. </para>
  97. <section xml:id="ns-web-xml">
  98. <title><literal>web.xml</literal> Configuration</title>
  99. <para> The first thing you need to do is add the following filter declaration to your
  100. <literal>web.xml</literal> file: <programlisting language="xml"><![CDATA[
  101. <filter>
  102. <filter-name>springSecurityFilterChain</filter-name>
  103. <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
  104. </filter>
  105. <filter-mapping>
  106. <filter-name>springSecurityFilterChain</filter-name>
  107. <url-pattern>/*</url-pattern>
  108. </filter-mapping>]]>
  109. </programlisting> This provides a hook into the Spring Security web
  110. infrastructure. <classname>DelegatingFilterProxy</classname> is a Spring Framework class
  111. which delegates to a filter implementation which is defined as a Spring bean in your
  112. application context. In this case, the bean is named
  113. <quote>springSecurityFilterChain</quote>, which is an internal infrastructure bean created
  114. by the namespace to handle web security. Note that you should not use this bean name
  115. yourself. Once you've added this to your <filename>web.xml</filename>, you're ready to start
  116. editing your application context file. Web security services are configured using the
  117. <literal>&lt;http&gt;</literal> element. </para>
  118. </section>
  119. <section xml:id="ns-minimal">
  120. <title>A Minimal <literal>&lt;http&gt;</literal> Configuration</title>
  121. <para> All you need to enable web security to begin with is <programlisting language="xml"><![CDATA[
  122. <http auto-config='true'>
  123. <intercept-url pattern="/**" access="ROLE_USER" />
  124. </http>
  125. ]]>
  126. </programlisting> Which says that we want all URLs within our application to be secured,
  127. requiring the role <literal>ROLE_USER</literal> to access them. The
  128. <literal>&lt;http></literal> element is the parent for all web-related namespace
  129. functionality. The <literal>&lt;intercept-url></literal> element defines a
  130. <literal>pattern</literal> which is matched against the URLs of incoming requests using an
  131. ant path style syntax<footnote>
  132. <para>See the section on <link xlink:href="#request-matching">Request
  133. Matching</link> in the Web Application Infrastructure chapter for more details
  134. on how matches are actually performed.</para>
  135. </footnote>. The <literal>access</literal> attribute defines the access
  136. requirements for requests matching the given pattern. With the default configuration, this
  137. is typically a comma-separated list of roles, one of which a user must have to be allowed to
  138. make the request. The prefix <quote>ROLE_</quote> is a marker which indicates that a simple
  139. comparison with the user's authorities should be made. In other words, a normal role-based
  140. check should be used. Access-control in Spring Security is not limited to the use of simple
  141. roles (hence the use of the prefix to differentiate between different types of security
  142. attributes). We'll see later how the interpretation can vary<footnote><para>The
  143. interpretation of the comma-separated values in the <literal>access</literal> attribute
  144. depends on the implementation of the <link xlink:href="#ns-access-manager"
  145. >AccessDecisionManager</link> which is used. In Spring Security 3.0, the attribute can
  146. also be populated with an <link xlink:href="#el-access">EL
  147. expression</link>.</para></footnote>.</para>
  148. <note>
  149. <para>You can use multiple <literal>&lt;intercept-url&gt;</literal> elements to define
  150. different access requirements for different sets of URLs, but they will be evaluated in
  151. the order listed and the first match will be used. So you must put the most specific
  152. matches at the top. You can also add a <literal>method</literal> attribute to limit the
  153. match to a particular HTTP method (<literal>GET</literal>, <literal>POST</literal>,
  154. <literal>PUT</literal> etc.). If a request matches multiple patterns, the
  155. method-specific match will take precedence regardless of ordering.</para>
  156. </note>
  157. <para> To add some users, you can define a set of test data directly in the namespace: <programlisting language="xml"><![CDATA[
  158. <authentication-manager>
  159. <authentication-provider>
  160. <user-service>
  161. <user name="jimi" password="jimispassword" authorities="ROLE_USER, ROLE_ADMIN" />
  162. <user name="bob" password="bobspassword" authorities="ROLE_USER" />
  163. </user-service>
  164. </authentication-provider>
  165. </authentication-manager>
  166. ]]>
  167. </programlisting></para>
  168. <sidebar>
  169. <para>If you are familiar with pre-namespace versions of the framework, you can probably
  170. already guess roughly what's going on here. The <literal>&lt;http&gt;</literal> element is
  171. responsible for creating a <classname>FilterChainProxy</classname> and the filter beans
  172. which it uses. Common problems like incorrect filter ordering are no longer an issue as
  173. the filter positions are predefined.</para>
  174. <para>The <literal>&lt;authentication-provider&gt;</literal> element creates a
  175. <classname>DaoAuthenticationProvider</classname> bean and the
  176. <literal>&lt;user-service&gt;</literal> element creates an
  177. <classname>InMemoryDaoImpl</classname>. All <literal>authentication-provider</literal>
  178. elements must be children of the <literal>&lt;authentication-manager></literal> element,
  179. which creates a <classname>ProviderManager</classname> and registers the authentication
  180. providers with it. You can find more detailed information on the beans that are created in
  181. the <link xlink:href="#appendix-namespace">namespace appendix</link>. It's worth
  182. cross-checking this if you want to start understanding what the important classes in the
  183. framework are and how they are used, particularly if you want to customise things
  184. later.</para>
  185. </sidebar>
  186. <para> The configuration above defines two users, their passwords and their roles within the
  187. application (which will be used for access control). It is also possible to load user
  188. information from a standard properties file using the <literal>properties</literal>
  189. attribute on <literal>user-service</literal>. See the section on <link
  190. xlink:href="#core-services-in-memory-service">in-memory authentication</link> for more
  191. details on the file format. Using the <literal>&lt;authentication-provider&gt;</literal>
  192. element means that the user information will be used by the authentication manager to
  193. process authentication requests. You can have multiple
  194. <literal>&lt;authentication-provider&gt;</literal> elements to define different
  195. authentication sources and each will be consulted in turn.</para>
  196. <para> At this point you should be able to start up your application and you will be required
  197. to log in to proceed. Try it out, or try experimenting with the <quote>tutorial</quote>
  198. sample application that comes with the project. The above configuration actually adds quite
  199. a few services to the application because we have used the <literal>auto-config</literal>
  200. attribute. For example, form-based login processing is automatically enabled. </para>
  201. <section xml:id="ns-auto-config">
  202. <title>What does <literal>auto-config</literal> Include?</title>
  203. <para> The <literal>auto-config</literal> attribute, as we have used it above, is just a
  204. shorthand syntax for: <programlisting language="xml"><![CDATA[
  205. <http>
  206. <form-login />
  207. <http-basic />
  208. <logout />
  209. </http>
  210. ]]></programlisting> These other elements are responsible for setting up form-login, basic
  211. authentication and logout handling services respectively <footnote><para>In versions prior
  212. to 3.0, this list also included remember-me functionality. This could cause some
  213. confusing errors with some configurations and was removed in 3.0. In 3.0, the addition
  214. of an <classname>AnonymousAuthenticationFilter</classname> is part of the default
  215. <literal>&lt;http></literal> configuration, so the <literal>&lt;anonymous
  216. /></literal> element is added regardless of whether <literal>auto-config</literal>
  217. is enabled.</para></footnote> . They each have attributes which can be used to alter
  218. their behaviour. </para>
  219. </section>
  220. <section xml:id="ns-form-and-basic">
  221. <title>Form and Basic Login Options</title>
  222. <para> You might be wondering where the login form came from when you were prompted to log
  223. in, since we made no mention of any HTML files or JSPs. In fact, since we didn't
  224. explicitly set a URL for the login page, Spring Security generates one automatically,
  225. based on the features that are enabled and using standard values for the URL which
  226. processes the submitted login, the default target URL the user will be sent to after
  227. loggin in and so on. However, the namespace offers plenty of support to allow you to
  228. customize these options. For example, if you want to supply your own login page, you could
  229. use: <programlisting language="xml"><![CDATA[
  230. <http auto-config='true'>
  231. <intercept-url pattern="/login.jsp*" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
  232. <intercept-url pattern="/**" access="ROLE_USER" />
  233. <form-login login-page='/login.jsp'/>
  234. </http>
  235. ]]>
  236. </programlisting> Note that you can still use <literal>auto-config</literal>. The
  237. <literal>form-login</literal> element just overrides the default settings. Also note
  238. that we've added an extra <literal>intercept-url</literal> element to say that any
  239. requests for the login page should be available to anonymous users <footnote><para>See the
  240. chapter on <link xlink:href="#anonymous">anonymous authentication</link> and also the
  241. <link xlink:href="#authz-authenticated-voter">AuthenticatedVoter</link> class for
  242. more details on how the value <literal>IS_AUTHENTICATED_ANONYMOUSLY</literal> is
  243. processed.</para></footnote>. Otherwise the request would be matched by the pattern
  244. <literal>/**</literal> and it wouldn't be possible to access the login page itself! This
  245. is a common configuration error and will result in an infinite loop in the application.
  246. Spring Security will emit a warning in the log if your login page appears to be secured.
  247. It is also possible to have all requests matching a particular pattern bypass the security
  248. filter chain completely: <programlisting language="xml"><![CDATA[
  249. <http auto-config='true'>
  250. <intercept-url pattern="/css/**" filters="none"/>
  251. <intercept-url pattern="/login.jsp*" filters="none"/>
  252. <intercept-url pattern="/**" access="ROLE_USER" />
  253. <form-login login-page='/login.jsp'/>
  254. </http>
  255. ]]>
  256. </programlisting>It's important to realise that these requests will be completely
  257. oblivious to any further Spring Security web-related configuration or additional
  258. attributes such as <literal>requires-channel</literal>, so you will not be able to access
  259. information on the current user or call secured methods during the request. Use
  260. <literal>access='IS_AUTHENTICATED_ANONYMOUSLY'</literal> as an alternative if you still
  261. want the security filter chain to be applied.
  262. <note>
  263. <para>Using <literal>filters="none"</literal> operates by creating an empty filter
  264. chain in Spring Security's <classname>FilterChainProxy</classname>, whereas
  265. the access attributes are used to configure the
  266. <classname>FilterSecurityInterceptor</classname> in the single filter chain
  267. which is created by the namespace configuration. The two are applied
  268. independently, so if you have an access contraint for a sub-pattern of a
  269. pattern which has a <literal>filters="none"</literal> attribute, the access
  270. constraint will be ignored, even if it is listed first. It isn't possible to
  271. apply a <literal>filters="none"</literal> attribute to the pattern
  272. <literal>/**</literal> since this is used by the namespace filter chain. In
  273. version 3.1 things are more flexible. You can define multiple filter chains
  274. and the <literal>filters</literal> attribute is no longer supported.</para>
  275. </note>
  276. </para>
  277. <para>If you want to use basic authentication instead of form login, then change the
  278. configuration to <programlisting language="xml"><![CDATA[
  279. <http auto-config='true'>
  280. <intercept-url pattern="/**" access="ROLE_USER" />
  281. <http-basic />
  282. </http>
  283. ]]>
  284. </programlisting> Basic authentication will then take precedence and will be used to
  285. prompt for a login when a user attempts to access a protected resource. Form login is
  286. still available in this configuration if you wish to use it, for example through a login
  287. form embedded in another web page. </para>
  288. <section xml:id="ns-form-target">
  289. <title>Setting a Default Post-Login Destination</title>
  290. <para> If a form login isn't prompted by an attempt to access a protected resource, the
  291. <literal>default-target-url</literal> option comes into play. This is the URL the user
  292. will be taken to after logging in, and defaults to "/". You can also configure things so
  293. that they user <emphasis>always</emphasis> ends up at this page (regardless of whether
  294. the login was "on-demand" or they explicitly chose to log in) by setting the
  295. <literal>always-use-default-target</literal> attribute to "true". This is useful if
  296. your application always requires that the user starts at a "home" page, for example: <programlisting language="xml"><![CDATA[
  297. <http>
  298. <intercept-url pattern='/login.htm*' filters='none'/>
  299. <intercept-url pattern='/**' access='ROLE_USER' />
  300. <form-login login-page='/login.htm' default-target-url='/home.htm'
  301. always-use-default-target='true' />
  302. </http>
  303. ]]>
  304. </programlisting></para>
  305. </section>
  306. </section>
  307. </section>
  308. <section xml:id="ns-auth-providers">
  309. <title>Using other Authentication Providers</title>
  310. <para> In practice you will need a more scalable source of user information than a few names
  311. added to the application context file. Most likely you will want to store your user
  312. information in something like a database or an LDAP server. LDAP namespace configuration is
  313. dealt with in the <link xlink:href="#ldap">LDAP chapter</link>, so we won't cover it here.
  314. If you have a custom implementation of Spring Security's
  315. <classname>UserDetailsService</classname>, called "myUserDetailsService" in your
  316. application context, then you can authenticate against this using <programlisting language="xml"><![CDATA[
  317. <authentication-manager>
  318. <authentication-provider user-service-ref='myUserDetailsService'/>
  319. </authentication-manager>
  320. ]]>
  321. </programlisting> If you want to use a database, then you can use <programlisting language="xml"><![CDATA[
  322. <authentication-manager>
  323. <authentication-provider>
  324. <jdbc-user-service data-source-ref="securityDataSource"/>
  325. </authentication-provider>
  326. </authentication-manager>
  327. ]]>
  328. </programlisting> Where <quote>securityDataSource</quote> is the name of a
  329. <classname>DataSource</classname> bean in the application context, pointing at a database
  330. containing the standard Spring Security <link xlink:href="#db_schema_users_authorities">user
  331. data tables</link>. Alternatively, you could configure a Spring Security
  332. <classname>JdbcDaoImpl</classname> bean and point at that using the
  333. <literal>user-service-ref</literal> attribute: <programlisting language="xml"><![CDATA[
  334. <authentication-manager>
  335. <authentication-provider user-service-ref='myUserDetailsService'/>
  336. </authentication-manager>
  337. <beans:bean id="myUserDetailsService"
  338. class="org.springframework.security.core.userdetails.jdbc.JdbcDaoImpl">
  339. <beans:property name="dataSource" ref="dataSource"/>
  340. </beans:bean>
  341. ]]>
  342. </programlisting> You can also use standard
  343. <interfacename>AuthenticationProvider</interfacename> beans as follows <programlisting language="xml"><![CDATA[
  344. <authentication-manager>
  345. <authentication-provider ref='myAuthenticationProvider'/>
  346. </authentication-manager>
  347. ]]>
  348. </programlisting> where <literal>myAuthenticationProvider</literal> is the name of a
  349. bean in your application context which implements
  350. <interfacename>AuthenticationProvider</interfacename>. You can use multiple
  351. <literal>authentication-provider</literal> elements, in which case they will be checked
  352. in the order they are declared when attempting to authenticated a user. See <xref
  353. linkend="ns-auth-manager"/> for more on information on how the Spring Security
  354. <interfacename>AuthenticationManager</interfacename> is configured using the namespace. </para>
  355. <section xml:id="ns-password-encoder">
  356. <title>Adding a Password Encoder</title>
  357. <para> Often your password data will be encoded using a hashing algorithm. This is supported
  358. by the <literal>&lt;password-encoder&gt;</literal> element. With SHA encoded passwords,
  359. the original authentication provider configuration would look like this: <programlisting language="xml"><![CDATA[
  360. <authentication-manager>
  361. <authentication-provider>
  362. <password-encoder hash="sha"/>
  363. <user-service>
  364. <user name="jimi" password="d7e6351eaa13189a5a3641bab846c8e8c69ba39f"
  365. authorities="ROLE_USER, ROLE_ADMIN" />
  366. <user name="bob" password="4e7421b1b8765d8f9406d87e7cc6aa784c4ab97f"
  367. authorities="ROLE_USER" />
  368. </user-service>
  369. </authentication-provider>
  370. </authentication-manager>
  371. ]]>
  372. </programlisting></para>
  373. <para> When using hashed passwords, it's also a good idea to use a salt value to protect
  374. against dictionary attacks and Spring Security supports this too. Ideally you would want
  375. to use a randomly generated salt value for each user, but you can use any property of the
  376. <classname>UserDetails</classname> object which is loaded by your
  377. <classname>UserDetailsService</classname>. For example, to use the
  378. <literal>username</literal> property, you would use <programlisting><![CDATA[
  379. <password-encoder hash="sha">
  380. <salt-source user-property="username"/>
  381. </password-encoder>
  382. ]]></programlisting> You can use a custom password encoder bean by using the
  383. <literal>ref</literal> attribute of <literal>password-encoder</literal>. This should
  384. contain the name of a bean in the application context which is an instance of Spring
  385. Security's <interfacename>PasswordEncoder</interfacename> interface. </para>
  386. </section>
  387. </section>
  388. </section>
  389. <section xml:id="ns-web-advanced">
  390. <title>Advanced Web Features</title>
  391. <section xml:id="ns-remember-me">
  392. <title>Remember-Me Authentication</title>
  393. <para>See the separate <link xlink:href="#remember-me">Remember-Me chapter</link> for
  394. information on remember-me namespace configuration.</para>
  395. </section>
  396. <section xml:id="ns-requires-channel">
  397. <title>Adding HTTP/HTTPS Channel Security</title>
  398. <para>If your application supports both HTTP and HTTPS, and you require that particular URLs
  399. can only be accessed over HTTPS, then this is directly supported using the
  400. <literal>requires-channel</literal> attribute on <literal>&lt;intercept-url&gt;</literal>: <programlisting language="xml"><![CDATA[
  401. <http>
  402. <intercept-url pattern="/secure/**" access="ROLE_USER" requires-channel="https"/>
  403. <intercept-url pattern="/**" access="ROLE_USER" requires-channel="any"/>
  404. ...
  405. </http>]]>
  406. </programlisting>With this configuration in place, if a user attempts to access
  407. anything matching the "/secure/**" pattern using HTTP, they will first be redirected to an
  408. HTTPS URL. The available options are "http", "https" or "any". Using the value "any" means
  409. that either HTTP or HTTPS can be used. </para>
  410. <para>If your application uses non-standard ports for HTTP and/or HTTPS, you can specify a
  411. list of port mappings as follows: <programlisting><![CDATA[
  412. <http>
  413. ...
  414. <port-mappings>
  415. <port-mapping http="9080" https="9443"/>
  416. </port-mappings>
  417. </http>]]>
  418. </programlisting><!--You can find a more in-depth discussion of channel security
  419. in <xref xlink:href="#channel-security"/--></para>
  420. </section>
  421. <section xml:id="ns-session-mgmt">
  422. <title>Session Management</title>
  423. <section>
  424. <title>Detecting Timeouts</title>
  425. <para> You can configure Spring Security to detect the submission of an invalid session ID
  426. and redirect the user to an appropriate URL. This is achieved through the
  427. <literal>session-management</literal> element: <programlisting language="xml"><![CDATA[
  428. <http>
  429. ...
  430. <session-management invalid-session-url="/sessionTimeout.htm" />
  431. </http>]]></programlisting></para>
  432. </section>
  433. <section xml:id="ns-concurrent-sessions">
  434. <title>Concurrent Session Control</title>
  435. <para>If you wish to place constraints on a single user's ability to log in to your
  436. application, Spring Security supports this out of the box with the following simple
  437. additions. First you need to add the following listener to your
  438. <filename>web.xml</filename> file to keep Spring Security updated about session
  439. lifecycle events: <programlisting language="xml"><![CDATA[
  440. <listener>
  441. <listener-class>
  442. org.springframework.security.web.session.HttpSessionEventPublisher
  443. </listener-class>
  444. </listener>
  445. ]]></programlisting> Then add the following lines to your application context: <programlisting language="xml"><![CDATA[
  446. <http>
  447. ...
  448. <session-management>
  449. <concurrency-control max-sessions="1" />
  450. </session-management>
  451. </http>]]>
  452. </programlisting> This will prevent a user from logging in multiple times - a
  453. second login will cause the first to be invalidated. Often you would prefer to prevent a
  454. second login, in which case you can use <programlisting language="xml"><![CDATA[
  455. <http>
  456. ...
  457. <session-management>
  458. <concurrency-control max-sessions="1" error-if-maximum-exceeded="true" />
  459. </session-management>
  460. </http>]]>
  461. </programlisting>The second login will then be rejected. By
  462. <quote>rejected</quote>, we mean that the user will be sent to the
  463. <literal>authentication-failure-url</literal> if form-based login is being used. If the
  464. second authentication takes place through another non-interactive mechanism, such as
  465. <quote>remember-me</quote>, an <quote>unauthorized</quote> (402) error will be sent to
  466. the client. If instead you want to use an error page, you can add the attribute
  467. <literal>session-authentication-error-url</literal> to the
  468. <literal>session-management</literal> element. </para>
  469. <para>If you are using a customized authentication filter for form-based login, then you
  470. have to configure concurrent session control support explicitly. More details can be found
  471. in the <link xlink:href="#session-mgmt">Session Management chapter</link>. </para>
  472. </section>
  473. <section xml:id="ns-session-fixation">
  474. <title>Session Fixation Attack Protection</title>
  475. <para>
  476. <link xlink:href="http://en.wikipedia.org/wiki/Session_fixation">Session fixation</link>
  477. attacks are a potential risk where it is possible for a malicious attacker to create a
  478. session by accessing a site, then persuade another user to log in with the same session
  479. (by sending them a link containing the session identifier as a parameter, for example).
  480. Spring Security protects against this automatically by creating a new session when a user
  481. logs in. If you don't require this protection, or it conflicts with some other
  482. requirement, you can control the behaviour using the
  483. <literal>session-fixation-protection</literal> attribute on
  484. <literal>&lt;session-management&gt;</literal>, which has three options
  485. <itemizedlist><listitem><para><literal>migrateSession</literal> - creates a new
  486. session and copies the existing session attributes to the new session. This is the
  487. default.</para></listitem><listitem><para><literal>none</literal> - Don't do
  488. anything. The original session will be
  489. retained.</para></listitem><listitem><para><literal>newSession</literal> - Create
  490. a new "clean" session, without copying the existing session
  491. data.</para></listitem></itemizedlist></para>
  492. </section>
  493. </section>
  494. <section xml:id="ns-openid">
  495. <title>OpenID Support</title>
  496. <para>The namespace supports <link xlink:href="http://openid.net/">OpenID</link> login either
  497. instead of, or in addition to normal form-based login, with a simple change: <programlisting language="xml"><![CDATA[
  498. <http>
  499. <intercept-url pattern="/**" access="ROLE_USER" />
  500. <openid-login />
  501. </http>
  502. ]]></programlisting>You should then register yourself with an OpenID provider (such as
  503. myopenid.com), and add the user information to your in-memory
  504. <literal>&lt;user-service&gt;</literal> : <programlisting language="xml"><![CDATA[
  505. <user name="http://jimi.hendrix.myopenid.com/" authorities="ROLE_USER" />
  506. ]]></programlisting> You should be able to login using the <literal>myopenid.com</literal> site to
  507. authenticate. It is also possible to select a specific
  508. <interfacename>UserDetailsService</interfacename> bean for use OpenID by setting the
  509. <literal>user-service-ref</literal> attribute on the <literal>openid-login</literal>
  510. element. See the previous section on <link xlink:href="#ns-auth-providers">authentication
  511. providers</link> for more information. Note that we have omitted the password attribute
  512. from the above user configuration, since this set of user data is only being used to load
  513. the authorities for the user. A random password will be generate internally, preventing you
  514. from accidentally using this user data as an authentication source elsewhere in your
  515. configuration.</para>
  516. <section>
  517. <title>Attribute Exchange</title>
  518. <para>Support for OpenID <link
  519. xlink:href="http://openid.net/specs/openid-attribute-exchange-1_0.html">attribute
  520. exchange</link>. As an example, the following configuration would attempt to retrieve
  521. the email and full name from the OpenID provider, for use by the application:<programlisting language="xml"><![CDATA[
  522. <openid-login>
  523. <attribute-exchange>
  524. <openid-attribute name="email" type="http://axschema.org/contact/email" required="true" />
  525. <openid-attribute name="name" type="http://axschema.org/namePerson" />
  526. </attribute-exchange>
  527. </openid-login>]]></programlisting>The <quote>type</quote> of each OpenID attribute is a URI,
  528. determined by a particular schema, in this case <link xlink:href="http://axschema.org/"
  529. >http://axschema.org/</link>. If an attribute must be retrieved for successful
  530. authentication, the <literal>required</literal> attribute can be set. The exact schema and
  531. attributes supported will depend on your OpenID provider. The attribute values are
  532. returned as part of the authentication process and can be accessed afterwards using the
  533. following
  534. code:<programlisting language="java">OpenIDAuthenticationToken token = (OpenIDAuthenticationToken)SecurityContextHolder.getContext().getAuthentication();
  535. List&lt;OpenIDAttribute> attributes = token.getAttributes();</programlisting>The
  536. <classname>OpenIDAttribute</classname> contains the attribute type and the retrieved
  537. value (or values in the case of multi-valued attributes). We'll see more about how the
  538. <classname>SecurityContextHolder</classname> class is used when we look at core Spring
  539. Security components in the <link xlink:href="#core-components">technical overview</link>
  540. chapter.</para>
  541. </section>
  542. </section>
  543. <section xml:id="ns-custom-filters">
  544. <title>Adding in Your Own Filters</title>
  545. <para>If you've used Spring Security before, you'll know that the framework maintains a chain
  546. of filters in order to apply its services. You may want to add your own filters to the stack
  547. at particular locations or use a Spring Security filter for which there isn't currently a
  548. namespace configuration option (CAS, for example). Or you might want to use a customized
  549. version of a standard namespace filter, such as the
  550. <literal>UsernamePasswordAuthenticationFilter</literal> which is created by the
  551. <literal>&lt;form-login&gt;</literal> element, taking advantage of some of the extra
  552. configuration options which are available by using the bean explicitly. How can you do this
  553. with namespace configuration, since the filter chain is not directly exposed? </para>
  554. <para>The order of the filters is always strictly enforced when using the namespace. When the
  555. application context is being created, the filter beans are sorted by the namespace handling
  556. code and the standard Spring Security filters each have an alias in the namespace and a
  557. well-known position.<note><para>In previous versions, the sorting took place after the
  558. filter instances had been created, during post-processing of the application context. In
  559. version 3.0+ the sorting is now done at the bean metadata level, before the classes have
  560. been instantiated. This has implications for how you add your own filters to the stack
  561. as the entire filter list must be known during the parsing of the
  562. <literal>&lt;http></literal> element, so the syntax has changed slightly in
  563. 3.0.</para></note>The filters, aliases and namespace elements/attributes which create
  564. the filters are shown in <xref linkend="filter-stack"/>. The filters are listed in the order
  565. in which they occur in the filter chain. <table xml:id="filter-stack"><title>Standard Filter
  566. Aliases and Ordering</title><tgroup cols="3" align="left"><thead><row><entry
  567. align="center">Alias</entry><entry align="center">Filter Class</entry><entry
  568. align="center">Namespace Element or
  569. Attribute</entry></row></thead><tbody><row><entry>
  570. CHANNEL_FILTER</entry><entry><literal>ChannelProcessingFilter</literal></entry><entry><literal>http/intercept-url@requires-channel</literal></entry></row><row><entry>
  571. CONCURRENT_SESSION_FILTER</entry><entry><literal>ConcurrentSessionFilter</literal>
  572. </entry><entry><literal>session-management/concurrency-control</literal></entry></row><row><entry>
  573. SECURITY_CONTEXT_FILTER</entry><entry><classname>SecurityContextPersistenceFilter</classname></entry><entry><literal>http</literal></entry></row><row><entry>
  574. LOGOUT_FILTER
  575. </entry><entry><literal>LogoutFilter</literal></entry><entry><literal>http/logout</literal></entry></row><row><entry>
  576. X509_FILTER
  577. </entry><entry><literal>X509AuthenticationFilter</literal></entry><entry><literal>http/x509</literal></entry></row><row><entry>
  578. PRE_AUTH_FILTER
  579. </entry><entry><literal>AstractPreAuthenticatedProcessingFilter</literal>
  580. Subclasses</entry><entry>N/A</entry></row><row><entry> CAS_FILTER
  581. </entry><entry><literal>CasAuthenticationFilter</literal></entry><entry>N/A</entry></row><row><entry>
  582. FORM_LOGIN_FILTER
  583. </entry><entry><literal>UsernamePasswordAuthenticationFilter</literal></entry><entry><literal>http/form-login</literal></entry></row><row><entry>
  584. BASIC_AUTH_FILTER
  585. </entry><entry><literal>BasicAuthenticationFilter</literal></entry><entry><literal>http/http-basic</literal></entry></row><row><entry>
  586. SERVLET_API_SUPPORT_FILTER</entry><entry><literal>SecurityContextHolderAwareFilter</literal></entry><entry><literal>http/@servlet-api-provision</literal></entry></row><row><entry>
  587. REMEMBER_ME_FILTER
  588. </entry><entry><classname>RememberMeAuthenticationFilter</classname></entry><entry><literal>http/remember-me</literal></entry></row><row><entry>
  589. ANONYMOUS_FILTER
  590. </entry><entry><literal>AnonymousAuthenticationFilter</literal></entry><entry><literal>http/anonymous</literal></entry></row><row><entry>
  591. SESSION_MANAGEMENT_FILTER</entry><entry><literal>SessionManagementFilter</literal></entry><entry><literal>session-management</literal></entry></row><row><entry>EXCEPTION_TRANSLATION_FILTER
  592. </entry><entry><classname>ExceptionTranslationFilter</classname></entry><entry><literal>http</literal></entry></row><row><entry>
  593. FILTER_SECURITY_INTERCEPTOR
  594. </entry><entry><classname>FilterSecurityInterceptor</classname></entry><entry><literal>http</literal></entry></row><row><entry>
  595. SWITCH_USER_FILTER
  596. </entry><entry><literal>SwitchUserFilter</literal></entry><entry>N/A</entry></row></tbody></tgroup></table>
  597. You can add your own filter to the stack, using the <literal>custom-filter</literal> element
  598. and one of these names to specify the position your filter should appear at: <programlisting language="xml"><![CDATA[
  599. <http>
  600. <custom-filter position="FORM_LOGIN_FILTER" ref="myFilter" />
  601. </http>
  602. <beans:bean id="myFilter" class="com.mycompany.MySpecialAuthenticationFilter"/>
  603. ]]>
  604. </programlisting> You can also use the <literal>after</literal> or <literal>before</literal>
  605. attributes if you want your filter to be inserted before or after another filter in the
  606. stack. The names "FIRST" and "LAST" can be used with the <literal>position</literal>
  607. attribute to indicate that you want your filter to appear before or after the entire stack,
  608. respectively. </para>
  609. <tip>
  610. <title>Avoiding filter position conflicts</title>
  611. <para> If you are inserting a custom filter which may occupy the same position as one of the
  612. standard filters created by the namespace then it's important that you don't include the
  613. namespace versions by mistake. Avoid using the <literal>auto-config</literal> attribute
  614. and remove any elements which create filters whose functionality you want to replace. </para>
  615. <para> Note that you can't replace filters which are created by the use of the
  616. <literal>&lt;http&gt;</literal> element itself -
  617. <classname>SecurityContextPersistenceFilter</classname>,
  618. <classname>ExceptionTranslationFilter</classname> or
  619. <classname>FilterSecurityInterceptor</classname>. </para>
  620. </tip>
  621. <para> If you're replacing a namespace filter which requires an authentication entry point
  622. (i.e. where the authentication process is triggered by an attempt by an unauthenticated user
  623. to access to a secured resource), you will need to add a custom entry point bean too. </para>
  624. <section xml:id="ns-entry-point-ref">
  625. <title>Setting a Custom <interfacename>AuthenticationEntryPoint</interfacename></title>
  626. <para> If you aren't using form login, OpenID or basic authentication through the namespace,
  627. you may want to define an authentication filter and entry point using a traditional bean
  628. syntax and link them into the namespace, as we've just seen. The corresponding
  629. <interfacename>AuthenticationEntryPoint</interfacename> can be set using the
  630. <literal>entry-point-ref</literal> attribute on the <literal>&lt;http&gt;</literal>
  631. element. </para>
  632. <para> The CAS sample application is a good example of the use of custom beans with the
  633. namespace, including this syntax. If you aren't familiar with authentication entry points,
  634. they are discussed in the <link xlink:href="#tech-intro-auth-entry-point">technical
  635. overview</link> chapter. </para>
  636. </section>
  637. </section>
  638. </section>
  639. <section xml:id="ns-method-security">
  640. <title>Method Security</title>
  641. <para>From version 2.0 onwards Spring Security has improved support substantially for adding
  642. security to your service layer methods. It provides support for JSR-250 annotation security as
  643. well as the framework's original <literal>@Secured</literal> annotation. From 3.0 you can also
  644. make use of new <link xlink:href="#el-access">expression-based annotations</link>. You can
  645. apply security to a single bean, using the <literal>intercept-methods</literal> element to
  646. decorate the bean declaration, or you can secure multiple beans across the entire service
  647. layer using the AspectJ style pointcuts. </para>
  648. <section xml:id="ns-global-method">
  649. <title>The <literal>&lt;global-method-security&gt;</literal> Element</title>
  650. <para> This element is used to enable annotation-based security in your application (by
  651. setting the appropriate attributes on the element), and also to group together security
  652. pointcut declarations which will be applied across your entire application context. You
  653. should only declare one <literal>&lt;global-method-security&gt;</literal> element. The
  654. following declaration would enable support for Spring Security's
  655. <literal>@Secured</literal>: <programlisting><![CDATA[
  656. <global-method-security secured-annotations="enabled" />
  657. ]]>
  658. </programlisting> Adding an annotation to a method (on an class or interface) would then limit
  659. the access to that method accordingly. Spring Security's native annotation support defines a
  660. set of attributes for the method. These will be passed to the
  661. <interfacename>AccessDecisionManager</interfacename> for it to make the actual decision:
  662. <programlisting language="java">
  663. public interface BankService {
  664. @Secured("IS_AUTHENTICATED_ANONYMOUSLY")
  665. public Account readAccount(Long id);
  666. @Secured("IS_AUTHENTICATED_ANONYMOUSLY")
  667. public Account[] findAccounts();
  668. @Secured("ROLE_TELLER")
  669. public Account post(Account account, double amount);
  670. }
  671. </programlisting>Support
  672. for JSR-250 annotations can be enabled using <programlisting><![CDATA[
  673. <global-method-security jsr250-annotations="enabled" />
  674. ]]>
  675. </programlisting>These are standards-based and allow simple role-based constraints to be
  676. applied but do not have the power Spring Security's native annotations.
  677. To use the new expression-based syntax, you would use
  678. <programlisting><![CDATA[
  679. <global-method-security pre-post-annotations="enabled" />
  680. ]]></programlisting>and the equivalent Java code would
  681. be<programlisting language="java">
  682. public interface BankService {
  683. @PreAuthorize("isAnonymous()")
  684. public Account readAccount(Long id);
  685. @PreAuthorize("isAnonymous()")
  686. public Account[] findAccounts();
  687. @PreAuthorize("hasAuthority('ROLE_TELLER')")
  688. public Account post(Account account, double amount);
  689. }
  690. </programlisting>Expression-based
  691. annotations are a good choice if you need to define simple rules that go beyond checking the
  692. role names against the user's list of authorities. You can enable more than one type of
  693. annotation in the same application, but you should avoid mixing annotations types in the
  694. same interface or class to avoid confusion.</para>
  695. <section xml:id="ns-protect-pointcut">
  696. <title>Adding Security Pointcuts using <literal>protect-pointcut</literal></title>
  697. <para> The use of <literal>protect-pointcut</literal> is particularly powerful, as it allows
  698. you to apply security to many beans with only a simple declaration. Consider the following
  699. example: <programlisting language="xml"><![CDATA[
  700. <global-method-security>
  701. <protect-pointcut expression="execution(* com.mycompany.*Service.*(..))"
  702. access="ROLE_USER"/>
  703. </global-method-security>
  704. ]]>
  705. </programlisting> This will protect all methods on beans declared in the application
  706. context whose classes are in the <literal>com.mycompany</literal> package and whose class
  707. names end in "Service". Only users with the <literal>ROLE_USER</literal> role will be able
  708. to invoke these methods. As with URL matching, the most specific matches must come first
  709. in the list of pointcuts, as the first matching expression will be used. </para>
  710. </section>
  711. </section>
  712. </section>
  713. <section xml:id="ns-access-manager">
  714. <title>The Default AccessDecisionManager</title>
  715. <para> This section assumes you have some knowledge of the underlying architecture for
  716. access-control within Spring Security. If you don't you can skip it and come back to it later,
  717. as this section is only really relevant for people who need to do some customization in order
  718. to use more than simple role-based security. </para>
  719. <para> When you use a namespace configuration, a default instance of
  720. <interfacename>AccessDecisionManager</interfacename> is automatically registered for you and
  721. will be used for making access decisions for method invocations and web URL access, based on
  722. the access attributes you specify in your <literal>intercept-url</literal> and
  723. <literal>protect-pointcut</literal> declarations (and in annotations if you are using
  724. annotation secured methods). </para>
  725. <para> The default strategy is to use an <classname>AffirmativeBased</classname>
  726. <interfacename>AccessDecisionManager</interfacename> with a <classname>RoleVoter</classname>
  727. and an <classname>AuthenticatedVoter</classname>. You can find out more about these in the
  728. chapter on <link xlink:href="authorization">authorization</link>.</para>
  729. <section xml:id="ns-custom-access-mgr">
  730. <title>Customizing the AccessDecisionManager</title>
  731. <para> If you need to use a more complicated access control strategy then it is easy to set an
  732. alternative for both method and web security. </para>
  733. <para> For method security, you do this by setting the
  734. <literal>access-decision-manager-ref</literal> attribute on
  735. <literal>global-method-security</literal> to the Id of the appropriate
  736. <interfacename>AccessDecisionManager</interfacename> bean in the application context: <programlisting language="xml"><![CDATA[
  737. <global-method-security access-decision-manager-ref="myAccessDecisionManagerBean">
  738. ...
  739. </global-method-security>
  740. ]]></programlisting></para>
  741. <para> The syntax for web security is the same, but on the <literal>http</literal> element: <programlisting language="xml"><![CDATA[
  742. <http access-decision-manager-ref="myAccessDecisionManagerBean">
  743. ...
  744. </http>
  745. ]]></programlisting></para>
  746. </section>
  747. </section>
  748. <section xml:id="ns-auth-manager">
  749. <title>The Authentication Manager and the Namespace</title>
  750. <para> The main interface which provides authentication services in Spring Security is the
  751. <interfacename>AuthenticationManager</interfacename>. This is usually an instance of Spring
  752. Security's <classname>ProviderManager</classname> class, which you may already be familiar
  753. with if you've used the framework before. If not, it will be covered later, in the <link
  754. xlink:href="#tech-intro-authentication">technical overview chapter</link>. The bean instance
  755. is registered using the <literal>authentication-manager</literal> namespace element. You can't
  756. use a custom <classname>AuthenticationManager</classname> if you are using either HTTP or
  757. method security through the namespace, but this should not be a problem as you have full
  758. control over the <classname>AuthenticationProvider</classname>s that are used.</para>
  759. <para> You may want to register additional <classname>AuthenticationProvider</classname> beans
  760. with the <classname>ProviderManager</classname> and you can do this using the
  761. <literal>&lt;authentication-provider&gt;</literal> element with the <literal>ref</literal>
  762. attribute, where the value of the attribute is the name of the provider bean you want to add.
  763. For example: <programlisting language="xml"><![CDATA[
  764. <authentication-manager>
  765. <authentication-provider ref="casAuthenticationProvider"/>
  766. </authentication-manager>
  767. <bean id="casAuthenticationProvider"
  768. class="org.springframework.security.cas.authentication.CasAuthenticationProvider">
  769. ...
  770. </bean>
  771. ]]></programlisting></para>
  772. <para> Another common requirement is that another bean in the context may require a reference to
  773. the <interfacename>AuthenticationManager</interfacename>. You can easily register an alias for
  774. the <interfacename>AuthenticationManager</interfacename> and use this name elsewhere in your
  775. application context. <programlisting language="xml"><![CDATA[
  776. <security:authentication-manager alias="authenticationManager">
  777. ...
  778. </security:authentication-manager>
  779. <bean id="customizedFormLoginFilter"
  780. class="com.somecompany.security.web.CustomFormLoginFilter">
  781. <property name="authenticationManager" ref="authenticationManager"/>
  782. ...
  783. </bean>
  784. ]]></programlisting></para>
  785. </section>
  786. </chapter>