namespace-config.xml 66 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029
  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.
  10. It allows you to supplement the traditional Spring beans application context syntax with
  11. elements 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.html"
  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
  15. alternative configuration syntax which more closely matches the problem domain and hides
  16. the underlying complexity from the user. A simple element may conceal the fact that
  17. multiple beans and processing steps are being added to the application context. For
  18. example, adding the following element from the security namespace to an application
  19. context will start up an embedded LDAP 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
  23. attributes on the <literal>ldap-server</literal> element and the user is isolated from
  24. worrying about which beans they need to create and what the bean property names are. <footnote>
  25. <para>You can find out more about the use of the <literal>ldap-server</literal> element
  26. in the chapter on <link linkend="ldap">LDAP</link>.</para>
  27. </footnote>. Use of a good XML editor while editing the application context file should
  28. provide information on the attributes and elements that are available. We would
  29. recommend that you try out the <link
  30. xlink:href="http://www.springsource.com/products/sts">SpringSource Tool Suite</link> as
  31. it has special features for working with standard Spring namespaces. </para>
  32. <para> To start using the security namespace in your application context, you need to have
  33. the <literal>spring-security-config</literal> jar on your classpath. Then all you need
  34. to do is add the schema declaration to your application context file: <programlisting language="xml">
  35. <![CDATA[
  36. <beans xmlns="http://www.springframework.org/schema/beans"
  37. xmlns:security="http://www.springframework.org/schema/security"
  38. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  39. xsi:schemaLocation="http://www.springframework.org/schema/beans
  40. http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
  41. http://www.springframework.org/schema/security
  42. http://www.springframework.org/schema/security/spring-security.xsd">
  43. ...
  44. </beans>
  45. ]]></programlisting> In many of the examples you will see (and in the sample) applications, we
  46. will often use "security" as the default namespace rather than "beans", which means we
  47. can omit the prefix on all the security namespace elements, making the content easier to
  48. read. You may also want to do this if you have your application context divided up into
  49. separate files and have most of your security configuration in one of them. Your
  50. security application context file would then start like this <programlisting language="xml"><![CDATA[
  51. <beans:beans xmlns="http://www.springframework.org/schema/security"
  52. xmlns:beans="http://www.springframework.org/schema/beans"
  53. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  54. xsi:schemaLocation="http://www.springframework.org/schema/beans
  55. http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
  56. http://www.springframework.org/schema/security
  57. http://www.springframework.org/schema/security/spring-security.xsd">
  58. ...
  59. </beans:beans>
  60. ]]></programlisting> We'll assume this syntax is being used from now on in this chapter. </para>
  61. <section>
  62. <title>Design of the Namespace</title>
  63. <para> The namespace is designed to capture the most common uses of the framework and
  64. provide a simplified and concise syntax for enabling them within an application. The
  65. design is based around the large-scale dependencies within the framework, and can be
  66. divided up into the following areas: <itemizedlist>
  67. <listitem>
  68. <para> <emphasis>Web/HTTP Security</emphasis> - the most complex part. Sets up
  69. the filters and related service beans used to apply the framework
  70. authentication mechanisms, to secure URLs, render login and error pages and
  71. much more.</para>
  72. </listitem>
  73. <listitem>
  74. <para> <emphasis>Business Object (Method) Security</emphasis> - options for
  75. securing the service layer.</para>
  76. </listitem>
  77. <listitem>
  78. <para> <emphasis>AuthenticationManager</emphasis> - handles authentication
  79. requests from other parts of the framework.</para>
  80. </listitem>
  81. <listitem>
  82. <para> <emphasis>AccessDecisionManager</emphasis> - provides access decisions
  83. for web and method security. A default one will be registered, but you can
  84. also choose to use a custom one, declared using normal Spring bean
  85. syntax.</para>
  86. </listitem>
  87. <listitem>
  88. <para> <emphasis>AuthenticationProvider</emphasis>s - mechanisms against which
  89. the authentication manager authenticates users. The namespace provides
  90. supports for several standard options and also a means of adding custom
  91. beans declared using a traditional syntax. </para>
  92. </listitem>
  93. <listitem>
  94. <para> <emphasis>UserDetailsService</emphasis> - closely related to
  95. authentication providers, but often also required by other beans.</para>
  96. </listitem>
  97. <!-- todo: diagram and link to other sections which describe the interfaces -->
  98. </itemizedlist></para>
  99. <para>We'll see how to configure these in the following sections.</para>
  100. </section>
  101. </section>
  102. <section xml:id="ns-getting-started">
  103. <title>Getting Started with Security Namespace Configuration</title>
  104. <para> In this section, we'll look at how you can build up a namespace configuration to use
  105. some of the main features of the framework. Let's assume you initially want to get up
  106. and running as quickly as possible and add authentication support and access control to
  107. an existing web application, with a few test logins. Then we'll look at how to change
  108. over to authenticating against a database or other security repository. In later
  109. sections we'll introduce more advanced namespace configuration options. </para>
  110. <section xml:id="ns-web-xml">
  111. <title><literal>web.xml</literal> Configuration</title>
  112. <para> The first thing you need to do is add the following filter declaration to your
  113. <literal>web.xml</literal> file: <programlisting language="xml"><![CDATA[
  114. <filter>
  115. <filter-name>springSecurityFilterChain</filter-name>
  116. <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
  117. </filter>
  118. <filter-mapping>
  119. <filter-name>springSecurityFilterChain</filter-name>
  120. <url-pattern>/*</url-pattern>
  121. </filter-mapping>]]>
  122. </programlisting> This provides a hook into the Spring Security web
  123. infrastructure. <classname>DelegatingFilterProxy</classname> is a Spring Framework
  124. class which delegates to a filter implementation which is defined as a Spring bean
  125. in your application context. In this case, the bean is named
  126. <quote>springSecurityFilterChain</quote>, which is an internal infrastructure bean
  127. created by the namespace to handle web security. Note that you should not use this
  128. bean name yourself. Once you've added this to your <filename>web.xml</filename>,
  129. you're ready to start editing your application context file. Web security services
  130. are configured using the <literal>&lt;http&gt;</literal> element. </para>
  131. </section>
  132. <section xml:id="ns-minimal">
  133. <title>A Minimal <literal>&lt;http&gt;</literal> Configuration</title>
  134. <para> All you need to enable web security to begin with is <programlisting language="xml"><![CDATA[
  135. <http>
  136. <intercept-url pattern="/**" access="ROLE_USER" />
  137. <form-login />
  138. <logout />
  139. </http>
  140. ]]>
  141. </programlisting> Which says that we want all URLs within our application to be secured,
  142. requiring the role <literal>ROLE_USER</literal> to access them, we want to log in to
  143. the application using a form with username and password, and that we want a logout URL
  144. registered which will allow us to log out of the application.
  145. <literal>&lt;http></literal> element is the parent for all web-related namespace
  146. functionality. The <literal>&lt;intercept-url></literal> element defines a
  147. <literal>pattern</literal> which is matched against the URLs of incoming requests
  148. using an ant path style syntax<footnote>
  149. <para>See the section on <link linkend="request-matching">Request
  150. Matching</link> in the Web Application Infrastructure chapter for more details
  151. on how matches are actually performed.</para>
  152. </footnote>. You can also use regular-expression matching as an alternative (see the
  153. namespace appendix for more details). The <literal>access</literal> attribute
  154. defines the access requirements for requests matching the given pattern. With the
  155. default configuration, this is typically a comma-separated list of roles, one of
  156. which a user must have to be allowed to make the request. The prefix
  157. <quote>ROLE_</quote> is a marker which indicates that a simple comparison with the
  158. user's authorities should be made. In other words, a normal role-based check should
  159. be used. Access-control in Spring Security is not limited to the use of simple roles
  160. (hence the use of the prefix to differentiate between different types of security
  161. attributes). We'll see later how the interpretation can vary<footnote>
  162. <para>The interpretation of the comma-separated values in the
  163. <literal>access</literal> attribute depends on the implementation of the <link
  164. linkend="ns-access-manager">AccessDecisionManager</link> which is used. In
  165. Spring Security 3.0, the attribute can also be populated with an <link
  166. linkend="el-access">EL expression</link>.</para>
  167. </footnote>.</para>
  168. <note>
  169. <para>You can use multiple <literal>&lt;intercept-url&gt;</literal> elements to
  170. define different access requirements for different sets of URLs, but they will
  171. be evaluated in the order listed and the first match will be used. So you must
  172. put the most specific matches at the top. You can also add a
  173. <literal>method</literal> attribute to limit the match to a particular HTTP
  174. method (<literal>GET</literal>, <literal>POST</literal>, <literal>PUT</literal>
  175. etc.).</para>
  176. </note>
  177. <para> To add some users, you can define a set of test data directly in the namespace: <programlisting language="xml"><![CDATA[
  178. <authentication-manager>
  179. <authentication-provider>
  180. <user-service>
  181. <user name="jimi" password="jimispassword" authorities="ROLE_USER, ROLE_ADMIN" />
  182. <user name="bob" password="bobspassword" authorities="ROLE_USER" />
  183. </user-service>
  184. </authentication-provider>
  185. </authentication-manager>
  186. ]]>
  187. </programlisting></para>
  188. <sidebar>
  189. <para>If you are familiar with pre-namespace versions of the framework, you can
  190. probably already guess roughly what's going on here. The
  191. <literal>&lt;http&gt;</literal> element is responsible for creating a
  192. <classname>FilterChainProxy</classname> and the filter beans which it uses.
  193. Common problems like incorrect filter ordering are no longer an issue as the
  194. filter positions are predefined.</para>
  195. <para>The <literal>&lt;authentication-provider&gt;</literal> element creates a
  196. <classname>DaoAuthenticationProvider</classname> bean and the
  197. <literal>&lt;user-service&gt;</literal> element creates an
  198. <classname>InMemoryDaoImpl</classname>. All
  199. <literal>authentication-provider</literal> elements must be children of the
  200. <literal>&lt;authentication-manager></literal> element, which creates a
  201. <classname>ProviderManager</classname> and registers the authentication
  202. providers with it. You can find more detailed information on the beans that are
  203. created in the <link linkend="appendix-namespace">namespace appendix</link>.
  204. It's worth cross-checking this if you want to start understanding what the
  205. important classes in the framework are and how they are used, particularly if
  206. you want to customise things later.</para>
  207. </sidebar>
  208. <para> The configuration above defines two users, their passwords and their roles within
  209. the application (which will be used for access control). It is also possible to load
  210. user information from a standard properties file using the
  211. <literal>properties</literal> attribute on <literal>user-service</literal>. See the
  212. section on <link linkend="core-services-in-memory-service">in-memory
  213. authentication</link> for more details on the file format. Using the
  214. <literal>&lt;authentication-provider&gt;</literal> element means that the user
  215. information will be used by the authentication manager to process authentication
  216. requests. You can have multiple <literal>&lt;authentication-provider&gt;</literal>
  217. elements to define different authentication sources and each will be consulted in
  218. turn.</para>
  219. <para> At this point you should be able to start up your application and you will be
  220. required to log in to proceed. Try it out, or try experimenting with the
  221. <quote>tutorial</quote> sample application that comes with the project.</para>
  222. </section>
  223. <section xml:id="ns-form-and-basic">
  224. <title>Form and Basic Login Options</title>
  225. <para> You might be wondering where the login form came from when you were prompted to
  226. log in, since we made no mention of any HTML files or JSPs. In fact, since we didn't
  227. explicitly set a URL for the login page, Spring Security generates one
  228. automatically, based on the features that are enabled and using standard values for
  229. the URL which processes the submitted login, the default target URL the user will be
  230. sent to after logging in and so on. However, the namespace offers plenty of support
  231. to allow you to customize these options. For example, if you want to supply your own
  232. login page, you could use: <programlisting language="xml"><![CDATA[
  233. <http>
  234. <intercept-url pattern="/login.jsp*" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
  235. <intercept-url pattern="/**" access="ROLE_USER" />
  236. <form-login login-page='/login.jsp'/>
  237. </http>
  238. ]]>
  239. </programlisting> Also note
  240. that we've added an extra <literal>intercept-url</literal> element to say that any
  241. requests for the login page should be available to anonymous users <footnote>
  242. <para>See the chapter on <link linkend="anonymous">anonymous
  243. authentication</link> and also the <link linkend="authz-authenticated-voter"
  244. >AuthenticatedVoter</link> class for more details on how the value
  245. <literal>IS_AUTHENTICATED_ANONYMOUSLY</literal> is processed.</para>
  246. </footnote>. Otherwise the request would be matched by the pattern
  247. <literal>/**</literal> and it wouldn't be possible to access the login page itself!
  248. This is a common configuration error and will result in an infinite loop in the
  249. application. Spring Security will emit a warning in the log if your login page
  250. appears to be secured. It is also possible to have all requests matching a
  251. particular pattern bypass the security filter chain completely, by defining a
  252. separate <literal>http</literal> element for the pattern like this: <programlisting language="xml"><![CDATA[
  253. <http pattern="/css/**" security="none"/>
  254. <http pattern="/login.jsp*" security="none"/>
  255. <http>
  256. <intercept-url pattern="/**" access="ROLE_USER" />
  257. <form-login login-page='/login.jsp'/>
  258. </http>
  259. ]]>
  260. </programlisting> From Spring Security 3.1 it is now possible to use multiple
  261. <literal>http</literal> elements to define separate security filter chain
  262. configurations for different request patterns. If the <literal>pattern</literal>
  263. attribute is omitted from an <literal>http</literal> element, it matches all
  264. requests. Creating an unsecured pattern is a simple example of this syntax, where
  265. the pattern is mapped to an empty filter chain <footnote>
  266. <para>The use of multiple <literal>&lt;http&gt;</literal> elements is an important
  267. feature, allowing the namespace to simultaneously support both stateful and
  268. stateless paths within the same application, for example. The previous syntax,
  269. using the attribute <literal>filters="none"</literal> on an
  270. <literal>intercept-url</literal> element is incompatible with this change and is
  271. no longer supported in 3.1.</para>
  272. </footnote>. We'll look at this new syntax in more detail in the chapter on the
  273. <link linkend="filter-chains-with-ns">Security Filter Chain</link>. </para>
  274. <para> It's important to realise that these unsecured requests will be completely
  275. oblivious to any Spring Security web-related configuration or additional attributes
  276. such as <literal>requires-channel</literal>, so you will not be able to access
  277. information on the current user or call secured methods during the request. Use
  278. <literal>access='IS_AUTHENTICATED_ANONYMOUSLY'</literal> as an alternative if you
  279. still want the security filter chain to be applied.</para>
  280. <para>If you want to use basic authentication instead of form login, then change the
  281. configuration to <programlisting language="xml"><![CDATA[
  282. <http>
  283. <intercept-url pattern="/**" access="ROLE_USER" />
  284. <http-basic />
  285. </http>
  286. ]]>
  287. </programlisting> Basic authentication will then take precedence and will be used to
  288. prompt for a login when a user attempts to access a protected resource. Form login
  289. is still available in this configuration if you wish to use it, for example through
  290. a login form embedded in another web page. </para>
  291. <section xml:id="ns-form-target">
  292. <title>Setting a Default Post-Login Destination</title>
  293. <para> If a form login isn't prompted by an attempt to access a protected resource,
  294. the <literal>default-target-url</literal> option comes into play. This is the
  295. URL the user will be taken to after successfully logging in, and defaults to
  296. "/". You can also configure things so that the user <emphasis>always</emphasis>
  297. ends up at this page (regardless of whether the login was "on-demand" or they
  298. explicitly chose to log in) by setting the
  299. <literal>always-use-default-target</literal> attribute to "true". This is useful
  300. if your application always requires that the user starts at a "home" page, for
  301. example: <programlisting language="xml"><![CDATA[
  302. <http pattern="/login.htm*" security="none"/>
  303. <http>
  304. <intercept-url pattern='/**' access='ROLE_USER' />
  305. <form-login login-page='/login.htm' default-target-url='/home.htm'
  306. always-use-default-target='true' />
  307. </http>
  308. ]]> </programlisting></para>
  309. <para>For even more control over the destination, you can use the
  310. <literal>authentication-success-handler-ref</literal> attribute as an
  311. alternative to <literal>default-target-url</literal>. The referenced bean should
  312. be an instance of <interfacename>AuthenticationSuccessHandler</interfacename>.
  313. You'll find more on this in the <link linkend="form-login-flow-handling"
  314. >Core Filters</link> chapter and also in the namespace appendix, as well as
  315. information on how to customize the flow when authentication fails. </para>
  316. </section>
  317. </section>
  318. <section xml:id="ns-logout">
  319. <title>Logout Handling</title>
  320. <para>The <literal>logout</literal> element adds support for logging out by navigating
  321. to a particular URL. The default logout URL is <literal>/j_spring_security_logout</literal>,
  322. but you can set it to something else using the <literal>logout-url</literal> attribute.
  323. More information on other available attributes may be found in the namespace appendix.
  324. </para>
  325. </section>
  326. <section xml:id="ns-auth-providers">
  327. <title>Using other Authentication Providers</title>
  328. <para> In practice you will need a more scalable source of user information than a few
  329. names added to the application context file. Most likely you will want to store your
  330. user information in something like a database or an LDAP server. LDAP namespace
  331. configuration is dealt with in the <link linkend="ldap">LDAP chapter</link>, so
  332. we won't cover it here. If you have a custom implementation of Spring Security's
  333. <classname>UserDetailsService</classname>, called "myUserDetailsService" in your
  334. application context, then you can authenticate against this using <programlisting language="xml"><![CDATA[
  335. <authentication-manager>
  336. <authentication-provider user-service-ref='myUserDetailsService'/>
  337. </authentication-manager>
  338. ]]>
  339. </programlisting> If you want to use a database, then you can use <programlisting language="xml"><![CDATA[
  340. <authentication-manager>
  341. <authentication-provider>
  342. <jdbc-user-service data-source-ref="securityDataSource"/>
  343. </authentication-provider>
  344. </authentication-manager>
  345. ]]>
  346. </programlisting> Where <quote>securityDataSource</quote> is the name of a
  347. <classname>DataSource</classname> bean in the application context, pointing at a
  348. database containing the standard Spring Security <link
  349. linkend="db_schema_users_authorities">user data tables</link>. Alternatively,
  350. you could configure a Spring Security <classname>JdbcDaoImpl</classname> bean and
  351. point at that using the <literal>user-service-ref</literal> attribute: <programlisting language="xml"><![CDATA[
  352. <authentication-manager>
  353. <authentication-provider user-service-ref='myUserDetailsService'/>
  354. </authentication-manager>
  355. <beans:bean id="myUserDetailsService"
  356. class="org.springframework.security.core.userdetails.jdbc.JdbcDaoImpl">
  357. <beans:property name="dataSource" ref="dataSource"/>
  358. </beans:bean>
  359. ]]>
  360. </programlisting> You can also use standard
  361. <interfacename>AuthenticationProvider</interfacename> beans as follows <programlisting language="xml"><![CDATA[
  362. <authentication-manager>
  363. <authentication-provider ref='myAuthenticationProvider'/>
  364. </authentication-manager>
  365. ]]>
  366. </programlisting> where <literal>myAuthenticationProvider</literal> is the name of a
  367. bean in your application context which implements
  368. <interfacename>AuthenticationProvider</interfacename>. You can use multiple
  369. <literal>authentication-provider</literal> elements, in which case the providers
  370. will be queried in the order they are declared. See <xref linkend="ns-auth-manager"
  371. /> for more on information on how the Spring Security
  372. <interfacename>AuthenticationManager</interfacename> is configured using the
  373. namespace. </para>
  374. <section xml:id="ns-password-encoder">
  375. <title>Adding a Password Encoder</title>
  376. <para> Passwords should always be encoded using a secure hashing algorithm designed for the purpose
  377. (not a standard algorithm like SHA or MD5). This is supported by the
  378. <literal>&lt;password-encoder&gt;</literal> element. With bcrypt
  379. encoded passwords, the original authentication provider configuration would look
  380. like this: <programlisting language="xml"><![CDATA[
  381. <beans:bean name="bcryptEncoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder"/>
  382. <authentication-manager>
  383. <authentication-provider>
  384. <password-encoder ref="bcryptEncoder"/>
  385. <user-service>
  386. <user name="jimi" password="d7e6351eaa13189a5a3641bab846c8e8c69ba39f"
  387. authorities="ROLE_USER, ROLE_ADMIN" />
  388. <user name="bob" password="4e7421b1b8765d8f9406d87e7cc6aa784c4ab97f"
  389. authorities="ROLE_USER" />
  390. </user-service>
  391. </authentication-provider>
  392. </authentication-manager>
  393. ]]>
  394. </programlisting></para>
  395. <para>Bcrypt is a good choice for most cases, unless you have a legacy system which forces
  396. you to use a different algorithm. If you are using a simple hashing algorithm or, even worse,
  397. storing plain text passwords, then you should consider migrating to a more secure option like bcrypt.
  398. </para>
  399. </section>
  400. </section>
  401. </section>
  402. <section xml:id="ns-web-advanced">
  403. <title>Advanced Web Features</title>
  404. <section xml:id="ns-remember-me">
  405. <title>Remember-Me Authentication</title>
  406. <para>See the separate <link linkend="remember-me">Remember-Me chapter</link> for
  407. information on remember-me namespace configuration.</para>
  408. </section>
  409. <section xml:id="ns-requires-channel">
  410. <title>Adding HTTP/HTTPS Channel Security</title>
  411. <para>If your application supports both HTTP and HTTPS, and you require that particular
  412. URLs can only be accessed over HTTPS, then this is directly supported using the
  413. <literal>requires-channel</literal> attribute on
  414. <literal>&lt;intercept-url&gt;</literal>: <programlisting language="xml"><![CDATA[
  415. <http>
  416. <intercept-url pattern="/secure/**" access="ROLE_USER" requires-channel="https"/>
  417. <intercept-url pattern="/**" access="ROLE_USER" requires-channel="any"/>
  418. ...
  419. </http>]]>
  420. </programlisting>With this configuration in place, if a user attempts to access
  421. anything matching the "/secure/**" pattern using HTTP, they will first be redirected
  422. to an HTTPS URL
  423. <footnote><para>For more details on how channel-processing is implemented, see the Javadoc
  424. for <classname>ChannelProcessingFilter</classname> and related classes.
  425. </para></footnote>.
  426. The available options are "http", "https" or "any". Using the value
  427. "any" means that either HTTP or HTTPS can be used. </para>
  428. <para>If your application uses non-standard ports for HTTP and/or HTTPS, you can specify
  429. a list of port mappings as follows: <programlisting language="xml"><![CDATA[
  430. <http>
  431. ...
  432. <port-mappings>
  433. <port-mapping http="9080" https="9443"/>
  434. </port-mappings>
  435. </http>]]>
  436. </programlisting>
  437. Note that in order to be truly secure, an application should not use HTTP at all or switch
  438. between HTTP and HTTPS. It should start in HTTPS (with the user entering an HTTPS URL) and
  439. use a secure connection throughout to avoid any possibility of man-in-the-middle attacks.
  440. </para>
  441. </section>
  442. <section xml:id="ns-session-mgmt">
  443. <title>Session Management</title>
  444. <section>
  445. <title>Detecting Timeouts</title>
  446. <para> You can configure Spring Security to detect the submission of an invalid
  447. session ID and redirect the user to an appropriate URL. This is achieved through
  448. the <literal>session-management</literal> element: <programlisting language="xml"><![CDATA[
  449. <http>
  450. ...
  451. <session-management invalid-session-url="/invalidSession.htm" />
  452. </http>]]></programlisting>Note that if you use this mechanism to detect session timeouts, it
  453. may falsely report an error if the user logs out and then logs back in without
  454. closing the browser. This is because the session cookie is not cleared when you
  455. invalidate the session and will be resubmitted even if the user has logged out.
  456. You may be able to explicitly delete the JSESSIONID cookie on logging out, for
  457. example by using the following syntax in the logout handler: <programlisting language="xml"><![CDATA[
  458. <http>
  459. <logout delete-cookies="JSESSIONID" />
  460. </http>
  461. ]]></programlisting> Unfortunately this can't be guaranteed to work with every servlet container,
  462. so you will need to test it in your environment<footnote>
  463. <para>If you are running your application behind a proxy, you may also be able
  464. to remove the session cookie by configuring the proxy server. For example,
  465. using Apache HTTPD's mod_headers, the following directive would delete the
  466. <literal>JSESSIONID</literal> cookie by expiring it in the response to a
  467. logout request (assuming the application is deployed under the path
  468. <literal>/tutorial</literal>):
  469. <programlisting language="xml"> &lt;LocationMatch "/tutorial/j_spring_security_logout">
  470. Header always set Set-Cookie "JSESSIONID=;Path=/tutorial;Expires=Thu, 01 Jan 1970 00:00:00 GMT"
  471. &lt;/LocationMatch></programlisting></para>
  472. </footnote>. </para>
  473. </section>
  474. <section xml:id="ns-concurrent-sessions">
  475. <title>Concurrent Session Control</title>
  476. <para>If you wish to place constraints on a single user's ability to log in to your
  477. application, Spring Security supports this out of the box with the following
  478. simple additions. First you need to add the following listener to your
  479. <filename>web.xml</filename> file to keep Spring Security updated about session
  480. lifecycle events: <programlisting language="xml"><![CDATA[
  481. <listener>
  482. <listener-class>
  483. org.springframework.security.web.session.HttpSessionEventPublisher
  484. </listener-class>
  485. </listener>
  486. ]]></programlisting> Then add the following lines to your application context: <programlisting language="xml"><![CDATA[
  487. <http>
  488. ...
  489. <session-management>
  490. <concurrency-control max-sessions="1" />
  491. </session-management>
  492. </http>]]>
  493. </programlisting> This will prevent a user from logging in multiple times - a
  494. second login will cause the first to be invalidated. Often you would prefer to
  495. prevent a second login, in which case you can use <programlisting language="xml"><![CDATA[
  496. <http>
  497. ...
  498. <session-management>
  499. <concurrency-control max-sessions="1" error-if-maximum-exceeded="true" />
  500. </session-management>
  501. </http>]]>
  502. </programlisting>The second login will then be rejected. By
  503. <quote>rejected</quote>, we mean that the user will be sent to the
  504. <literal>authentication-failure-url</literal> if form-based login is being used.
  505. If the second authentication takes place through another non-interactive
  506. mechanism, such as <quote>remember-me</quote>, an <quote>unauthorized</quote>
  507. (401) error will be sent to the client. If instead you want to use an error
  508. page, you can add the attribute
  509. <literal>session-authentication-error-url</literal> to the
  510. <literal>session-management</literal> element. </para>
  511. <para>If you are using a customized authentication filter for form-based login, then
  512. you have to configure concurrent session control support explicitly. More
  513. details can be found in the <link linkend="session-mgmt">Session Management
  514. chapter</link>. </para>
  515. </section>
  516. <section xml:id="ns-session-fixation">
  517. <title>Session Fixation Attack Protection</title>
  518. <para> <link xlink:href="http://en.wikipedia.org/wiki/Session_fixation">Session
  519. fixation</link> attacks are a potential risk where it is possible for a
  520. malicious attacker to create a session by accessing a site, then persuade
  521. another user to log in with the same session (by sending them a link containing
  522. the session identifier as a parameter, for example). Spring Security protects
  523. against this automatically by creating a new session or otherwise changing the
  524. session ID when a user logs in. If you don't require this protection, or it
  525. conflicts with some other requirement, you can control the behavior using the
  526. <literal>session-fixation-protection</literal> attribute on
  527. <literal>&lt;session-management&gt;</literal>, which has four options <itemizedlist>
  528. <listitem>
  529. <para><literal>none</literal> - Don't do anything. The original session will
  530. be retained.</para>
  531. </listitem>
  532. <listitem>
  533. <para><literal>newSession</literal> - Create a new "clean" session, without
  534. copying the existing session data (Spring Security-related attributes will
  535. still be copied).</para>
  536. </listitem>
  537. <listitem>
  538. <para><literal>migrateSession</literal> - Create a new session and copy
  539. all existing session attributes to the new session. This is the
  540. default in Servlet 3.0 or older containers.</para>
  541. </listitem>
  542. <listitem>
  543. <para><literal>changeSessionId</literal> - Do not create a new session.
  544. Instead, use the session fixation protection provided by the Servlet container
  545. (<literal>HttpServletRequest#changeSessionId()</literal>). This option is only
  546. available in Servlet 3.1 (Java EE 7) and newer containers. Specifying it in
  547. older containers will result in an exception. This is the default in Servlet
  548. 3.1 and newer containers.</para>
  549. </listitem>
  550. </itemizedlist>
  551. When session fixation protection occurs, it results in a
  552. <classname>SessionFixationProtectionEvent</classname> being published in the
  553. application context. If you use <literal>changeSessionId</literal>, this protection
  554. will <emphasis>also</emphasis> result in any
  555. <classname>javax.servlet.http.HttpSessionIdListener</classname>s being notified, so
  556. use caution if your code listens for both events. See the
  557. <link linkend="session-mgmt">Session Management</link> chapter for additional
  558. information.
  559. </para>
  560. </section>
  561. </section>
  562. <section xml:id="ns-openid">
  563. <title>OpenID Support</title>
  564. <para>The namespace supports <link xlink:href="http://openid.net/">OpenID</link> login
  565. either instead of, or in addition to normal form-based login, with a simple change: <programlisting language="xml"><![CDATA[
  566. <http>
  567. <intercept-url pattern="/**" access="ROLE_USER" />
  568. <openid-login />
  569. </http>
  570. ]]></programlisting>You should then register yourself with an OpenID provider (such as
  571. myopenid.com), and add the user information to your in-memory
  572. <literal>&lt;user-service&gt;</literal> : <programlisting language="xml"><![CDATA[
  573. <user name="http://jimi.hendrix.myopenid.com/" authorities="ROLE_USER" />
  574. ]]></programlisting> You should be able to login using the <literal>myopenid.com</literal> site to
  575. authenticate. It is also possible to select a specific
  576. <interfacename>UserDetailsService</interfacename> bean for use OpenID by setting the
  577. <literal>user-service-ref</literal> attribute on the <literal>openid-login</literal>
  578. element. See the previous section on <link linkend="ns-auth-providers"
  579. >authentication providers</link> for more information. Note that we have omitted the
  580. password attribute from the above user configuration, since this set of user data is
  581. only being used to load the authorities for the user. A random password will be
  582. generate internally, preventing you from accidentally using this user data as an
  583. authentication source elsewhere in your configuration.</para>
  584. <section>
  585. <title>Attribute Exchange</title>
  586. <para>Support for OpenID <link
  587. xlink:href="http://openid.net/specs/openid-attribute-exchange-1_0.html"
  588. >attribute exchange</link>. As an example, the following configuration would
  589. attempt to retrieve the email and full name from the OpenID provider, for use by
  590. the application:<programlisting language="xml"><![CDATA[
  591. <openid-login>
  592. <attribute-exchange>
  593. <openid-attribute name="email" type="http://axschema.org/contact/email" required="true"/>
  594. <openid-attribute name="name" type="http://axschema.org/namePerson"/>
  595. </attribute-exchange>
  596. </openid-login>]]></programlisting>The <quote>type</quote> of each OpenID attribute is a URI,
  597. determined by a particular schema, in this case <link
  598. xlink:href="http://axschema.org/">http://axschema.org/</link>. If an attribute
  599. must be retrieved for successful authentication, the <literal>required</literal>
  600. attribute can be set. The exact schema and attributes supported will depend on
  601. your OpenID provider. The attribute values are returned as part of the
  602. authentication process and can be accessed afterwards using the following code:
  603. <programlisting language="java">
  604. OpenIDAuthenticationToken token =
  605. (OpenIDAuthenticationToken)SecurityContextHolder.getContext().getAuthentication();
  606. List&lt;OpenIDAttribute> attributes = token.getAttributes();</programlisting>The
  607. <classname>OpenIDAttribute</classname> contains the attribute type and the
  608. retrieved value (or values in the case of multi-valued attributes). We'll see
  609. more about how the <classname>SecurityContextHolder</classname> class is used
  610. when we look at core Spring Security components in the <link
  611. linkend="core-components">technical overview</link> chapter. Multiple
  612. attribute exchange configurations are also be supported, if you wish to use
  613. multiple identity providers. You can supply multiple
  614. <literal>attribute-exchange</literal> elements, using an
  615. <literal>identifier-matcher</literal> attribute on each. This contains a regular
  616. expression which will be matched against the OpenID identifier supplied by the
  617. user. See the OpenID sample application in the codebase for an example
  618. configuration, providing different attribute lists for the Google, Yahoo and
  619. MyOpenID providers.</para>
  620. </section>
  621. </section>
  622. <section xml:id="ns-headers">
  623. <title>Response Headers</title>
  624. <para>A lot of different attacks to hijack content, sessions or connections are available and lately
  625. browsers (optionally) can help to prevent those attacks. To enable these features we need to send some
  626. additional headers to the client. Spring Security allows for easy configuration for several headers.
  627. <programlisting language="xml"><![CDATA[
  628. <http ...>
  629. ...
  630. <headers/>
  631. </http>]]>
  632. </programlisting>
  633. </para>
  634. <para>Specifying the single headers element adds all the explicitly supported headers
  635. with their default settings. If you only want select headers to be added,
  636. you can add one or more of the child elements as shown below.
  637. <programlisting language="xml"><![CDATA[
  638. <http ...>
  639. ...
  640. <headers>
  641. <!-- Add Cache-Control, Pragma, and Expires headers -->
  642. <cache-control/>
  643. <!-- Add X-Content-Type-Options with value of nosniff -->
  644. <content-type-options/>
  645. <!-- Add custom headers -->
  646. <header name="foo" value="bar"/>
  647. <-- Adds HTTP Strict Transport Security (HSTS) for secure requests -->
  648. <hsts/>
  649. <!-- Add X-Frame-Options with a value of DENY -->
  650. <frame-options/>
  651. <!-- Adds X-XSS-Protection with value of 1; mode=block-->
  652. <xss-protection/>
  653. </headers>
  654. </http>]]>
  655. </programlisting>
  656. </para>
  657. <para>For additional information on how to customize the headers element refer to the <link linkend="headers">Security Headers</link>
  658. section of the reference.</para>
  659. </section>
  660. <section xml:id="ns-custom-filters">
  661. <title>Adding in Your Own Filters</title>
  662. <para>If you've used Spring Security before, you'll know that the framework maintains a
  663. chain of filters in order to apply its services. You may want to add your own
  664. filters to the stack at particular locations or use a Spring Security filter for
  665. which there isn't currently a namespace configuration option (CAS, for example). Or
  666. you might want to use a customized version of a standard namespace filter, such as
  667. the <classname>UsernamePasswordAuthenticationFilter</classname> which is created by the
  668. <literal>&lt;form-login&gt;</literal> element, taking advantage of some of the extra
  669. configuration options which are available by using the bean explicitly. How can you
  670. do this with namespace configuration, since the filter chain is not directly
  671. exposed? </para>
  672. <para>The order of the filters is always strictly enforced when using the namespace.
  673. When the application context is being created, the filter beans are sorted by the
  674. namespace handling code and the standard Spring Security filters each have an alias
  675. in the namespace and a well-known position.<note>
  676. <para>In previous versions, the sorting took place after the filter instances had
  677. been created, during post-processing of the application context. In version 3.0+
  678. the sorting is now done at the bean metadata level, before the classes have been
  679. instantiated. This has implications for how you add your own filters to the
  680. stack as the entire filter list must be known during the parsing of the
  681. <literal>&lt;http></literal> element, so the syntax has changed slightly in
  682. 3.0.</para>
  683. </note>The filters, aliases and namespace elements/attributes which create the
  684. filters are shown in <xref linkend="filter-stack"/>. The filters are listed in the
  685. order in which they occur in the filter chain. <table xml:id="filter-stack">
  686. <title>Standard Filter Aliases and Ordering</title>
  687. <tgroup cols="3" align="left">
  688. <colspec colnum="1" colname="col1" colwidth="2*"/>
  689. <colspec colnum="2" colname="col2" colwidth="2*"/>
  690. <colspec colnum="3" colname="col3" colwidth="1*"/>
  691. <thead>
  692. <row>
  693. <entry align="center">Alias</entry>
  694. <entry align="center">Filter Class</entry>
  695. <entry align="center">Namespace Element or Attribute</entry>
  696. </row>
  697. </thead>
  698. <tbody>
  699. <row>
  700. <entry> CHANNEL_FILTER</entry>
  701. <entry><literal>ChannelProcessingFilter</literal></entry>
  702. <entry><literal>http/intercept-url@requires-channel</literal></entry>
  703. </row>
  704. <row>
  705. <entry> SECURITY_CONTEXT_FILTER</entry>
  706. <entry><classname>SecurityContextPersistenceFilter</classname></entry>
  707. <entry><literal>http</literal></entry>
  708. </row>
  709. <row>
  710. <entry> CONCURRENT_SESSION_FILTER</entry>
  711. <entry><literal>ConcurrentSessionFilter</literal> </entry>
  712. <entry><literal>session-management/concurrency-control</literal></entry>
  713. </row>
  714. <row>
  715. <entry>HEADERS_FILTER</entry>
  716. <entry><literal>HeaderWriterFilter</literal> </entry>
  717. <entry><literal>http/headers</literal></entry>
  718. </row>
  719. <row>
  720. <entry>CSRF_FILTER</entry>
  721. <entry><literal>CsrfFilter</literal> </entry>
  722. <entry><literal>http/csrf</literal></entry>
  723. </row>
  724. <row>
  725. <entry> LOGOUT_FILTER </entry>
  726. <entry><literal>LogoutFilter</literal></entry>
  727. <entry><literal>http/logout</literal></entry>
  728. </row>
  729. <row>
  730. <entry> X509_FILTER </entry>
  731. <entry><literal>X509AuthenticationFilter</literal></entry>
  732. <entry><literal>http/x509</literal></entry>
  733. </row>
  734. <row>
  735. <entry> PRE_AUTH_FILTER </entry>
  736. <entry><literal>AstractPreAuthenticatedProcessingFilter</literal>
  737. Subclasses</entry>
  738. <entry>N/A</entry>
  739. </row>
  740. <row>
  741. <entry> CAS_FILTER </entry>
  742. <entry><literal>CasAuthenticationFilter</literal></entry>
  743. <entry>N/A</entry>
  744. </row>
  745. <row>
  746. <entry> FORM_LOGIN_FILTER </entry>
  747. <entry><literal>UsernamePasswordAuthenticationFilter</literal></entry>
  748. <entry><literal>http/form-login</literal></entry>
  749. </row>
  750. <row>
  751. <entry> BASIC_AUTH_FILTER </entry>
  752. <entry><literal>BasicAuthenticationFilter</literal></entry>
  753. <entry><literal>http/http-basic</literal></entry>
  754. </row>
  755. <row>
  756. <entry> SERVLET_API_SUPPORT_FILTER</entry>
  757. <entry><literal>SecurityContextHolderAwareRequestFilter</literal></entry>
  758. <entry><literal>http/@servlet-api-provision</literal></entry>
  759. </row>
  760. <row>
  761. <entry>JAAS_API_SUPPORT_FILTER</entry>
  762. <entry><literal>JaasApiIntegrationFilter</literal></entry>
  763. <entry><literal>http/@jaas-api-provision</literal></entry>
  764. </row>
  765. <row>
  766. <entry> REMEMBER_ME_FILTER </entry>
  767. <entry><classname>RememberMeAuthenticationFilter</classname></entry>
  768. <entry><literal>http/remember-me</literal></entry>
  769. </row>
  770. <row>
  771. <entry> ANONYMOUS_FILTER </entry>
  772. <entry><literal>AnonymousAuthenticationFilter</literal></entry>
  773. <entry><literal>http/anonymous</literal></entry>
  774. </row>
  775. <row>
  776. <entry> SESSION_MANAGEMENT_FILTER</entry>
  777. <entry><literal>SessionManagementFilter</literal></entry>
  778. <entry><literal>session-management</literal></entry>
  779. </row>
  780. <row>
  781. <entry>EXCEPTION_TRANSLATION_FILTER </entry>
  782. <entry><classname>ExceptionTranslationFilter</classname></entry>
  783. <entry><literal>http</literal></entry>
  784. </row>
  785. <row>
  786. <entry> FILTER_SECURITY_INTERCEPTOR </entry>
  787. <entry><classname>FilterSecurityInterceptor</classname></entry>
  788. <entry><literal>http</literal></entry>
  789. </row>
  790. <row>
  791. <entry> SWITCH_USER_FILTER </entry>
  792. <entry><literal>SwitchUserFilter</literal></entry>
  793. <entry>N/A</entry>
  794. </row>
  795. </tbody>
  796. </tgroup>
  797. </table> You can add your own filter to the stack, using the
  798. <literal>custom-filter</literal> element and one of these names to specify the
  799. position your filter should appear at: <programlisting language="xml"><![CDATA[
  800. <http>
  801. <custom-filter position="FORM_LOGIN_FILTER" ref="myFilter" />
  802. </http>
  803. <beans:bean id="myFilter" class="com.mycompany.MySpecialAuthenticationFilter"/>
  804. ]]>
  805. </programlisting> You can also use the <literal>after</literal> or <literal>before</literal>
  806. attributes if you want your filter to be inserted before or after another filter in
  807. the stack. The names "FIRST" and "LAST" can be used with the
  808. <literal>position</literal> attribute to indicate that you want your filter to
  809. appear before or after the entire stack, respectively. </para>
  810. <tip>
  811. <title>Avoiding filter position conflicts</title>
  812. <para> If you are inserting a custom filter which may occupy the same position as
  813. one of the standard filters created by the namespace then it's important that
  814. you don't include the namespace versions by mistake. Remove any elements which create
  815. filters whose functionality you want to replace. </para>
  816. <para> Note that you can't replace filters which are created by the use of the
  817. <literal>&lt;http&gt;</literal> element itself -
  818. <classname>SecurityContextPersistenceFilter</classname>,
  819. <classname>ExceptionTranslationFilter</classname> or
  820. <classname>FilterSecurityInterceptor</classname>. Some other filters are added
  821. by default, but you can disable them. An <classname>AnonymousAuthenticationFilter</classname>
  822. is added by default and unless you have
  823. <link linkend="ns-session-fixation">session-fixation protection</link>
  824. disabled, a <classname>SessionManagementFilter</classname> will also be added
  825. to the filter chain.
  826. </para>
  827. </tip>
  828. <para> If you're replacing a namespace filter which requires an authentication entry
  829. point (i.e. where the authentication process is triggered by an attempt by an
  830. unauthenticated user to access to a secured resource), you will need to add a custom
  831. entry point bean too. </para>
  832. <section xml:id="ns-entry-point-ref">
  833. <title>Setting a Custom
  834. <interfacename>AuthenticationEntryPoint</interfacename></title>
  835. <para> If you aren't using form login, OpenID or basic authentication through the
  836. namespace, you may want to define an authentication filter and entry point using
  837. a traditional bean syntax and link them into the namespace, as we've just seen.
  838. The corresponding <interfacename>AuthenticationEntryPoint</interfacename> can be
  839. set using the <literal>entry-point-ref</literal> attribute on the
  840. <literal>&lt;http&gt;</literal> element. </para>
  841. <para> The CAS sample application is a good example of the use of custom beans with
  842. the namespace, including this syntax. If you aren't familiar with authentication
  843. entry points, they are discussed in the <link
  844. linkend="tech-intro-auth-entry-point">technical overview</link> chapter.
  845. </para>
  846. </section>
  847. </section>
  848. </section>
  849. <section xml:id="ns-method-security">
  850. <title>Method Security</title>
  851. <para>From version 2.0 onwards Spring Security has improved support substantially for adding
  852. security to your service layer methods. It provides support for JSR-250 annotation
  853. security as well as the framework's original <literal>@Secured</literal> annotation.
  854. From 3.0 you can also make use of new <link linkend="el-access">expression-based
  855. annotations</link>. You can apply security to a single bean, using the
  856. <literal>intercept-methods</literal> element to decorate the bean declaration, or you
  857. can secure multiple beans across the entire service layer using the AspectJ style
  858. pointcuts. </para>
  859. <section xml:id="ns-global-method">
  860. <title>The <literal>&lt;global-method-security&gt;</literal> Element</title>
  861. <para> This element is used to enable annotation-based security in your application (by
  862. setting the appropriate attributes on the element), and also to group together
  863. security pointcut declarations which will be applied across your entire application
  864. context. You should only declare one
  865. <literal>&lt;global-method-security&gt;</literal> element. The following declaration
  866. would enable support for Spring Security's <literal>@Secured</literal>: <programlisting language="xml"><![CDATA[
  867. <global-method-security secured-annotations="enabled" />
  868. ]]>
  869. </programlisting> Adding an annotation to a method (on an class or interface) would then limit
  870. the access to that method accordingly. Spring Security's native annotation support
  871. defines a set of attributes for the method. These will be passed to the
  872. <interfacename>AccessDecisionManager</interfacename> for it to make the actual
  873. decision:
  874. <programlisting language="java">
  875. public interface BankService {
  876. @Secured("IS_AUTHENTICATED_ANONYMOUSLY")
  877. public Account readAccount(Long id);
  878. @Secured("IS_AUTHENTICATED_ANONYMOUSLY")
  879. public Account[] findAccounts();
  880. @Secured("ROLE_TELLER")
  881. public Account post(Account account, double amount);
  882. }
  883. </programlisting>Support
  884. for JSR-250 annotations can be enabled using <programlisting language="xml"><![CDATA[
  885. <global-method-security jsr250-annotations="enabled" />
  886. ]]>
  887. </programlisting>These are standards-based and allow simple role-based constraints to
  888. be applied but do not have the power Spring Security's native annotations. To use
  889. the new expression-based syntax, you would use <programlisting language="xml"><![CDATA[
  890. <global-method-security pre-post-annotations="enabled" />
  891. ]]></programlisting>and the equivalent Java code would
  892. be<programlisting language="java">
  893. public interface BankService {
  894. @PreAuthorize("isAnonymous()")
  895. public Account readAccount(Long id);
  896. @PreAuthorize("isAnonymous()")
  897. public Account[] findAccounts();
  898. @PreAuthorize("hasAuthority('ROLE_TELLER')")
  899. public Account post(Account account, double amount);
  900. }
  901. </programlisting>Expression-based
  902. annotations are a good choice if you need to define simple rules that go beyond
  903. checking the role names against the user's list of authorities. <note>
  904. <para>The annotated methods will only be secured for instances which are defined as
  905. Spring beans (in the same application context in which method-security is
  906. enabled). If you want to secure instances which are not created by Spring (using
  907. the <literal>new</literal> operator, for example) then you need to use AspectJ.
  908. </para>
  909. </note>
  910. <note>
  911. <para>
  912. You can enable more than one type of annotation in the same application, but
  913. only one type should be used for any interface or class as the behaviour will not
  914. be well-defined otherwise. If two annotations are found which apply to a particular
  915. method, then only one of them will be applied.
  916. </para>
  917. </note> </para>
  918. <section xml:id="ns-protect-pointcut">
  919. <title>Adding Security Pointcuts using <literal>protect-pointcut</literal></title>
  920. <para> The use of <literal>protect-pointcut</literal> is particularly powerful, as
  921. it allows you to apply security to many beans with only a simple declaration.
  922. Consider the following example: <programlisting language="xml"><![CDATA[
  923. <global-method-security>
  924. <protect-pointcut expression="execution(* com.mycompany.*Service.*(..))"
  925. access="ROLE_USER"/>
  926. </global-method-security>
  927. ]]>
  928. </programlisting> This will protect all methods on beans declared in the application
  929. context whose classes are in the <literal>com.mycompany</literal> package and
  930. whose class names end in "Service". Only users with the
  931. <literal>ROLE_USER</literal> role will be able to invoke these methods. As with
  932. URL matching, the most specific matches must come first in the list of
  933. pointcuts, as the first matching expression will be used. Security
  934. annotations take precedence over pointcuts.
  935. </para>
  936. </section>
  937. </section>
  938. </section>
  939. <section xml:id="ns-access-manager">
  940. <title>The Default AccessDecisionManager</title>
  941. <para> This section assumes you have some knowledge of the underlying architecture for
  942. access-control within Spring Security. If you don't you can skip it and come back to it
  943. later, as this section is only really relevant for people who need to do some
  944. customization in order to use more than simple role-based security. </para>
  945. <para> When you use a namespace configuration, a default instance of
  946. <interfacename>AccessDecisionManager</interfacename> is automatically registered for you
  947. and will be used for making access decisions for method invocations and web URL access,
  948. based on the access attributes you specify in your <literal>intercept-url</literal> and
  949. <literal>protect-pointcut</literal> declarations (and in annotations if you are using
  950. annotation secured methods). </para>
  951. <para> The default strategy is to use an <classname>AffirmativeBased</classname>
  952. <interfacename>AccessDecisionManager</interfacename> with a
  953. <classname>RoleVoter</classname> and an <classname>AuthenticatedVoter</classname>. You
  954. can find out more about these in the chapter on <link linkend="authz-arch"
  955. >authorization</link>.</para>
  956. <section xml:id="ns-custom-access-mgr">
  957. <title>Customizing the AccessDecisionManager</title>
  958. <para> If you need to use a more complicated access control strategy then it is easy to
  959. set an alternative for both method and web security. </para>
  960. <para> For method security, you do this by setting the
  961. <literal>access-decision-manager-ref</literal> attribute on
  962. <literal>global-method-security</literal> to the <literal>id</literal> of the appropriate
  963. <interfacename>AccessDecisionManager</interfacename> bean in the application
  964. context: <programlisting language="xml"><![CDATA[
  965. <global-method-security access-decision-manager-ref="myAccessDecisionManagerBean">
  966. ...
  967. </global-method-security>
  968. ]]></programlisting></para>
  969. <para> The syntax for web security is the same, but on the <literal>http</literal>
  970. element: <programlisting language="xml"><![CDATA[
  971. <http access-decision-manager-ref="myAccessDecisionManagerBean">
  972. ...
  973. </http>
  974. ]]></programlisting></para>
  975. </section>
  976. </section>
  977. <section xml:id="ns-auth-manager">
  978. <title>The Authentication Manager and the Namespace</title>
  979. <para> The main interface which provides authentication services in Spring Security is the
  980. <interfacename>AuthenticationManager</interfacename>. This is usually an instance of
  981. Spring Security's <classname>ProviderManager</classname> class, which you may already be
  982. familiar with if you've used the framework before. If not, it will be covered later, in
  983. the <link linkend="tech-intro-authentication">technical overview chapter</link>. The
  984. bean instance is registered using the <literal>authentication-manager</literal>
  985. namespace element. You can't use a custom <classname>AuthenticationManager</classname>
  986. if you are using either HTTP or method security through the namespace, but this should
  987. not be a problem as you have full control over the
  988. <classname>AuthenticationProvider</classname>s that are used.</para>
  989. <para> You may want to register additional <classname>AuthenticationProvider</classname>
  990. beans with the <classname>ProviderManager</classname> and you can do this using the
  991. <literal>&lt;authentication-provider&gt;</literal> element with the
  992. <literal>ref</literal> attribute, where the value of the attribute is the name of the
  993. provider bean you want to add. For example: <programlisting language="xml"><![CDATA[
  994. <authentication-manager>
  995. <authentication-provider ref="casAuthenticationProvider"/>
  996. </authentication-manager>
  997. <bean id="casAuthenticationProvider"
  998. class="org.springframework.security.cas.authentication.CasAuthenticationProvider">
  999. ...
  1000. </bean>
  1001. ]]></programlisting></para>
  1002. <para> Another common requirement is that another bean in the context may require a
  1003. reference to the <interfacename>AuthenticationManager</interfacename>. You can easily
  1004. register an alias for the <interfacename>AuthenticationManager</interfacename> and use
  1005. this name elsewhere in your application context. <programlisting language="xml"><![CDATA[
  1006. <security:authentication-manager alias="authenticationManager">
  1007. ...
  1008. </security:authentication-manager>
  1009. <bean id="customizedFormLoginFilter"
  1010. class="com.somecompany.security.web.CustomFormLoginFilter">
  1011. <property name="authenticationManager" ref="authenticationManager"/>
  1012. ...
  1013. </bean>
  1014. ]]></programlisting></para>
  1015. </section>
  1016. </chapter>