core-services.xml 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. <chapter xmlns="http://docbook.org/ns/docbook" version="5.0" xml:id="core-services"
  2. xmlns:xlink="http://www.w3.org/1999/xlink">
  3. <title>Core Services</title>
  4. <para> Now that we have a high-level overview of the Spring Security architecture and its core
  5. classes, let's take a closer look at one or two of the core interfaces and their
  6. implementations, in particular the <interfacename>AuthenticationManager</interfacename>,
  7. <interfacename>UserDetailsService</interfacename> and the
  8. <interfacename>AccessDecisionManager</interfacename>. These crop up regularly throughout
  9. the remainder of this document so it's important you know how they are configured and how
  10. they operate. </para>
  11. <section xml:id="authentication-manager">
  12. <title>The <interfacename>AuthenticationManager</interfacename>,
  13. <classname>ProviderManager</classname> and
  14. <classname>AuthenticationProvider</classname>s</title>
  15. <para>The <interfacename>AuthenticationManager</interfacename> is just an interface, so the
  16. implementation can be anything we choose, but how does it work in practice? What if we
  17. need to check multiple authentication databases or a combination of different
  18. authentication services such as a database and an LDAP server?</para>
  19. <para>The default implementation in Spring Security is called
  20. <classname>ProviderManager</classname> and rather than handling the authentication
  21. request itself, it delegates to a list of configured
  22. <classname>AuthenticationProvider</classname>s, each of which is queried in turn to
  23. see if it can perform the authentication. Each provider will either throw an exception
  24. or return a fully populated <interfacename>Authentication</interfacename> object.
  25. Remember our good friends, <interfacename>UserDetails</interfacename> and
  26. <interfacename>UserDetailsService</interfacename>? If not, head back to the previous
  27. chapter and refresh your memory. The most common approach to verifying an authentication
  28. request is to load the corresponding <interfacename>UserDetails</interfacename> and
  29. check the loaded password against the one that has been entered by the user. This is the
  30. approach used by the <classname>DaoAuthenticationProvider</classname> (see below). The
  31. loaded <interfacename>UserDetails</interfacename> object - and particularly the
  32. <literal>GrantedAuthority</literal>s it contains - will be used when building the
  33. fully populated <interfacename>Authentication</interfacename> object which is returned
  34. from a successful authentication and stored in the
  35. <classname>SecurityContext</classname>. </para>
  36. <para> If you are using the namespace, an instance of
  37. <classname>ProviderMananger</classname> is created and maintained internally, and
  38. you add providers to it either by using the namespace authentication provider elements,
  39. or by adding the <literal>&lt;custom-authentication-provider&gt;</literal> element to a
  40. bean (see <link xlink:href="#ns-auth-manager">the namespace chapter</link>). In this
  41. case, you should not declare a <classname>ProviderManager</classname> bean in your
  42. application context. However, if you are not using the namespace then you would declare
  43. it like so: <programlisting language="xml"><![CDATA[
  44. <bean id="authenticationManager"
  45. class="org.springframework.security.authentication.ProviderManager">
  46. <property name="providers">
  47. <list>
  48. <ref local="daoAuthenticationProvider"/>
  49. <ref local="anonymousAuthenticationProvider"/>
  50. <ref local="ldapAuthenticationProvider"/>
  51. </list>
  52. </property>
  53. </bean>]]></programlisting></para>
  54. <para>In the above example we have three providers. They are tried in the order shown (which
  55. is implied by the use of a <literal>List</literal>), with each provider able to attempt
  56. authentication, or skip authentication by simply returning <literal>null</literal>. If
  57. all implementations return null, the <literal>ProviderManager</literal> will throw a
  58. <exceptionname>ProviderNotFoundException</exceptionname>. If you're interested in
  59. learning more about chaining providers, please refer to the
  60. <literal>ProviderManager</literal> JavaDocs.</para>
  61. <para> Authentication mechanisms such as a web form-login processing filter are injected
  62. with a reference to the <interfacename>ProviderManager</interfacename> and will call it
  63. to handle their authentication requests. The providers you require will sometimes be
  64. interchangeable with the authentication mechanisms, while at other times they will
  65. depend on a specific authentication mechanism. For example,
  66. <classname>DaoAuthenticationProvider</classname> and
  67. <classname>LdapAuthenticationProvider</classname> are compatible with any mechanism
  68. which submits a simple username/password authentication request and so will work with
  69. form-based logins or HTTP Basic authentication. On the other hand, some authentication
  70. mechanisms create an authentication request object which can only be interpreted by a
  71. single type of <classname>AuthenticationProvider</classname>. An example of this would
  72. be JA-SIG CAS, which uses the notion of a service ticket and so can therefore only be
  73. authenticated by a <classname>CasAuthenticationProvider</classname>. You needn't be too
  74. concerned about this, because if you forget to register a suitable provider, you'll
  75. simply receive a <literal>ProviderNotFoundException</literal> when an attempt to
  76. authenticate is made.</para>
  77. <section>
  78. <title><literal>DaoAuthenticationProvider</literal></title>
  79. <para>The simplest <interfacename>AuthenticationProvider</interfacename> implemented by
  80. Spring Security is <literal>DaoAuthenticationProvider</literal>, which is is also
  81. one of the earliest supported by the framework. It leverages a
  82. <interfacename>UserDetailsService</interfacename> (as a DAO) in order to lookup
  83. the username, password and <interfacename>GrantedAuthority</interfacename>s. It
  84. authenticates the user simply by comparing the password submitted in a
  85. <classname>UsernamePasswordAuthenticationToken</classname> against the one
  86. loaded by the <interfacename>UserDetailsService</interfacename>. Configuring the
  87. provider is quite simple: <programlisting language="xml"><![CDATA[
  88. <bean id="daoAuthenticationProvider"
  89. class="org.springframework.security.authentication.dao.DaoAuthenticationProvider">
  90. <property name="userDetailsService" ref="inMemoryDaoImpl"/>
  91. <property name="saltSource" ref bean="saltSource"/>
  92. <property name="passwordEncoder" ref="passwordEncoder"/>
  93. </bean>]]></programlisting> The <interfacename>PasswordEncoder</interfacename> and
  94. <interfacename>SaltSource</interfacename> are optional. A
  95. <interfacename>PasswordEncoder</interfacename> provides encoding and decoding of
  96. passwords presented in the <interfacename>UserDetails</interfacename> object that is
  97. returned from the configured <interfacename>UserDetailsService</interfacename>. A
  98. <interfacename>SaltSource</interfacename> enables the passwords to be populated
  99. with a "salt", which enhances the security of the passwords in the authentication
  100. repository. These will be discussed in more detail in ???.
  101. <!-- TODO: Add sections on password encoding and user caching to advaced topics -->
  102. </para>
  103. </section>
  104. </section>
  105. <section>
  106. <title><interfacename>UserDetailsService</interfacename> Implementations</title>
  107. <para>As mentioned in the earlier in this reference guide, most authentication providers
  108. take advantage of the <interfacename>UserDetails</interfacename> and
  109. <interfacename>UserDetailsService</interfacename> interfaces. Recall that the
  110. contract for <interfacename>UserDetailsService</interfacename> is a single
  111. method:</para>
  112. <para>
  113. <programlisting>
  114. UserDetails loadUserByUsername(String username) throws UsernameNotFoundException;
  115. </programlisting>
  116. </para>
  117. <para>The returned <interfacename>UserDetails</interfacename> is an interface that provides
  118. getters that guarantee non-null provision of authentication information such as the
  119. username, password, granted authorities and whether the user account is enabled or
  120. disabled. Most authentication providers will use a
  121. <interfacename>UserDetailsService</interfacename>, even if the username and password
  122. are not actually used as part of the authentication decision. They may use the returned
  123. <interfacename>UserDetails</interfacename> object just for its
  124. <literal>GrantedAuthority</literal> information, because some other system (like
  125. LDAP or X.509 or CAS etc) has undertaken the responsibility of actually validating the
  126. credentials.</para>
  127. <para>Given <interfacename>UserDetailsService</interfacename> is so simple to implement, it
  128. should be easy for users to retrieve authentication information using a persistence
  129. strategy of their choice. Having said that, Spring Security does include a couple of
  130. useful base implementations, which we'll look at below.</para>
  131. <section xml:id="in-memory-service">
  132. <title>In-Memory Authentication</title>
  133. <para>Is easy to use create a custom <interfacename>UserDetailsService</interfacename>
  134. implementation that extracts information from a persistence engine of choice, but
  135. many applications do not require such complexity. This is particularly true if
  136. you're building a prototype application or just starting integrating Spring
  137. Security, when you don't really want to spend time configuring databases or writing
  138. <interfacename>UserDetailsService</interfacename> implementations. For this sort
  139. of situation, a simple option is to use the <literal>user-service</literal> element
  140. from the security <link xlink:href="#namespace-minimal">namespace</link>: <programlisting><![CDATA[
  141. <user-service id="userDetailsService">
  142. <user name="jimi" password="jimispassword" authorities="ROLE_USER, ROLE_ADMIN" />
  143. <user name="bob" password="bobspassword" authorities="ROLE_USER" />
  144. </user-service>
  145. ]]>
  146. </programlisting> This also supports the use of an external properties
  147. file: <programlisting><![CDATA[
  148. <user-service id="userDetailsService" properties="users.properties"/>
  149. ]]></programlisting> The properties file should contain entries in the form
  150. <programlisting>username=password,grantedAuthority[,grantedAuthority][,enabled|disabled]</programlisting>
  151. For example
  152. <programlisting>
  153. jimi=jimispassword,ROLE_USER,ROLE_ADMIN,enabled
  154. bob=bobspassword,ROLE_USER,enabled</programlisting></para>
  155. </section>
  156. <section xml:id="jdbc-service">
  157. <title><literal>JdbcDaoImpl</literal></title>
  158. <para>Spring Security also includes a <interfacename>UserDetailsService</interfacename>
  159. that can obtain authentication information from a JDBC data source. Internally
  160. Spring JDBC is used, so it avoids the complexity of a fully-featured object
  161. relational mapper (ORM) just to store user details. If your application does use an
  162. ORM tool, you might prefer to write a custom
  163. <interfacename>UserDetailsService</interfacename> to reuse the mapping files
  164. you've probably already created. Returning to <literal>JdbcDaoImpl</literal>, an
  165. example configuration is shown below:</para>
  166. <para>
  167. <programlisting language="xml"><![CDATA[
  168. <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
  169. <property name="driverClassName" value="org.hsqldb.jdbcDriver"/>
  170. <property name="url" value="jdbc:hsqldb:hsql://localhost:9001"/>
  171. <property name="username" value="sa"/>
  172. <property name="password" value=""/>
  173. </bean>
  174. <bean id="userDetailsService" class="org.springframework.security.core.userdetails.jdbc.JdbcDaoImpl">
  175. <property name="dataSource" ref="dataSource"/>
  176. </bean> ]]> </programlisting>
  177. </para>
  178. <para>You can use different relational database management systems by modifying the
  179. <literal>DriverManagerDataSource</literal> shown above. You can also use a
  180. global data source obtained from JNDI, as with any other Spring
  181. configuration.</para>
  182. <section>
  183. <title>Authority Groups</title>
  184. <para>By default, <classname>JdbcDaoImpl</classname> loads the authorities for a
  185. single user with the assumption that the authorities are mapped directly to
  186. users (see the <link xlink:href="#appendix-schema">database schema
  187. appendix</link>). An alternative approach is to partition the authorities
  188. into groups and assign groups to the user. Some people prefer this approach as a
  189. means of administering user rights. See the <classname>JdbcDaoImpl</classname>
  190. Javadoc for more information on how to enable the use of group authorities. The
  191. group schema is also included in the appendix.</para>
  192. </section>
  193. <!--
  194. <para>If the default schema is unsuitable for your needs, <literal>JdbcDaoImpl</literal>
  195. provides properties that allow customisation of the SQL statements. Please refer to the
  196. JavaDocs for details, but note that the class is not intended for complex custom
  197. subclasses. If you have a complex schema or would like a custom
  198. <interfacename>UserDetails</interfacename> implementation returned, you'd be better off
  199. writing your own <interfacename>UserDetailsService</interfacename>. The base
  200. implementation provided with Spring Security is intended for typical situations, rather
  201. than catering for all possible requirements.</para>
  202. -->
  203. </section>
  204. </section>
  205. </chapter>