|
@@ -1,10 +1,7 @@
|
|
|
-<?xml version="1.0" encoding="UTF-8"?>
|
|
|
-<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
|
|
|
- "http://www.docbook.org/xml/4.4/docbookx.dtd">
|
|
|
-<chapter id="ldap">
|
|
|
- <title>LDAP Authentication</title>
|
|
|
- <sect1 id="ldap-overview">
|
|
|
- <title>Overview</title>
|
|
|
+<chapter xmlns="http://docbook.org/ns/docbook" version="5.0" xml:id="ldap"><info><title>LDAP Authentication</title></info>
|
|
|
+
|
|
|
+ <section xml:id="ldap-overview"><info><title>Overview</title></info>
|
|
|
+
|
|
|
<para>LDAP is often used by organizations as a central repository for user information and
|
|
|
as an authentication service. It can also be used to store the role information for
|
|
|
application users.</para>
|
|
@@ -14,17 +11,16 @@
|
|
|
configured to handle a wide range of situations.</para>
|
|
|
<para>You should be familiar with LDAP before trying to use it with Spring Security. The
|
|
|
following link provides a good introduction to the concepts involved and a guide to
|
|
|
- setting up a directory using the free LDAP server OpenLDAP: <ulink
|
|
|
- url="http://www.zytrax.com/books/ldap/"/>. Some familiarity with the JNDI APIs used
|
|
|
+ setting up a directory using the free LDAP server OpenLDAP: <uri xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://www.zytrax.com/books/ldap/">http://www.zytrax.com/books/ldap/</uri>. Some familiarity with the JNDI APIs used
|
|
|
to access LDAP from Java may also be useful. We don't use any third-party LDAP libraries
|
|
|
(Mozilla, JLDAP etc.) in the LDAP provider, but extensive use is made of Spring LDAP, so
|
|
|
some familiarity with that project may be useful if you plan on adding your own
|
|
|
customizations.</para>
|
|
|
- </sect1>
|
|
|
- <sect1>
|
|
|
- <title>Using LDAP with Spring Security</title>
|
|
|
+ </section>
|
|
|
+ <section><info><title>Using LDAP with Spring Security</title></info>
|
|
|
+
|
|
|
<para> LDAP authentication in Spring Security can be roughly divided into the following
|
|
|
- stages. <orderedlist>
|
|
|
+ stages. <orderedlist inheritnum="ignore" continuation="restarts">
|
|
|
<listitem>
|
|
|
<para>Obtaining the unique LDAP <quote>Distinguished Name</quote>, or DN, from
|
|
|
the login name. This will often mean performing a search in the directory,
|
|
@@ -45,57 +41,56 @@
|
|
|
<para> We will look at some configuration scenarios below. For full information on available
|
|
|
configuration options, please consult the security namespace schema (information from
|
|
|
which should be available in your XML editor). </para>
|
|
|
- </sect1>
|
|
|
- <sect1>
|
|
|
- <title>Configuring an LDAP Server</title>
|
|
|
+ </section>
|
|
|
+ <section><info><title>Configuring an LDAP Server</title></info>
|
|
|
+
|
|
|
<para> The first thing you need to do is configure the server against which authentication
|
|
|
should take place. This is done using the <literal><ldap-server></literal> element
|
|
|
from the security namespace. This can be configured to point at an external LDAP server,
|
|
|
- using the <literal>url</literal> attribute: <programlisting><![CDATA[
|
|
|
- <ldap-server url="ldap://springframework.org:389/dc=springframework,dc=org" />
|
|
|
- ]]></programlisting></para>
|
|
|
- <sect2>
|
|
|
- <title>Using an Embedded Test Server</title>
|
|
|
+ using the <literal>url</literal> attribute: <programlisting>
|
|
|
+ <ldap-server url="ldap://springframework.org:389/dc=springframework,dc=org" />
|
|
|
+ </programlisting></para>
|
|
|
+ <section><info><title>Using an Embedded Test Server</title></info>
|
|
|
+
|
|
|
<para> The <literal><ldap-server></literal> element can also be used to create an
|
|
|
embedded server, which can be very useful for testing and demonstrations. In this
|
|
|
- case you use it without the <literal>url</literal> attribute: <programlisting><![CDATA[
|
|
|
- <ldap-server root="dc=springframework,dc=org"/>
|
|
|
- ]]></programlisting> Here we've specified that the root DIT of the directory should be
|
|
|
+ case you use it without the <literal>url</literal> attribute: <programlisting>
|
|
|
+ <ldap-server root="dc=springframework,dc=org"/>
|
|
|
+ </programlisting> Here we've specified that the root DIT of the directory should be
|
|
|
<quote>dc=springframework,dc=org</quote>, which is the default. Used this way,
|
|
|
the namespace parser will create an embedded Apache Directory server and scan the
|
|
|
classpath for any LDIF files, which it will attempt to load into the server. You can
|
|
|
customize this behaviour using the <literal>ldif</literal> attribute, which defines
|
|
|
- an LDIF resource to be loaded: <programlisting><![CDATA[
|
|
|
- <ldap-server ldif="classpath:users.ldif" />
|
|
|
- ]]></programlisting> This makes it a lot easier to get up and running with LDAP, since it can be
|
|
|
+ an LDIF resource to be loaded: <programlisting>
|
|
|
+ <ldap-server ldif="classpath:users.ldif" />
|
|
|
+ </programlisting> This makes it a lot easier to get up and running with LDAP, since it can be
|
|
|
inconvenient to work all the time with an external server. It also insulates the
|
|
|
user from the complex bean configuration needed to wire up an Apache Directory
|
|
|
server. Using plain Spring Beans the configuration would be much more cluttered. You
|
|
|
must have the necessary Apache Directory dependency jars available for your
|
|
|
- application to use. These can be obtained from the <olink targetdoc="sample-apps"
|
|
|
- targetptr="ldap">LDAP sample application</olink>. </para>
|
|
|
- </sect2>
|
|
|
- <sect2>
|
|
|
- <title>Using Bind Authentication</title>
|
|
|
+ application to use. These can be obtained from the LDAP sample application. </para>
|
|
|
+ </section>
|
|
|
+ <section><info><title>Using Bind Authentication</title></info>
|
|
|
+
|
|
|
<para> This is the most common LDAP authentication scenario. <programlisting>
|
|
|
- <![CDATA[
|
|
|
- <ldap-authentication-provider user-dn-pattern="uid={0},ou=people"/>
|
|
|
- ]]></programlisting> This simple example would obtain the DN for the user by
|
|
|
+
|
|
|
+ <ldap-authentication-provider user-dn-pattern="uid={0},ou=people"/>
|
|
|
+ </programlisting> This simple example would obtain the DN for the user by
|
|
|
substituting the user login name in the supplied pattern and attempting to bind as
|
|
|
that user with the login password. This is OK if all your users are stored under a
|
|
|
single node in the directory. If instead you wished to configure an LDAP search
|
|
|
filter to locate the user, you could use the following: <programlisting>
|
|
|
- <![CDATA[
|
|
|
- <ldap-authentication-provider user-search-filter="(uid={0})" user-search-base="ou=people"/>
|
|
|
- ]]></programlisting> If used with the server definition above, this would
|
|
|
+
|
|
|
+ <ldap-authentication-provider user-search-filter="(uid={0})" user-search-base="ou=people"/>
|
|
|
+ </programlisting> If used with the server definition above, this would
|
|
|
perform a search under the DN <literal>ou=people,dc=springframework,dc=org</literal>
|
|
|
using the value of the <literal>user-search-filter</literal> attribute as a filter.
|
|
|
Again the user login name is substituted for the parameter in the filter name. If
|
|
|
<literal>user-search-base</literal> isn't supplied, the search will be performed
|
|
|
from the root. </para>
|
|
|
- </sect2>
|
|
|
- <sect2>
|
|
|
- <title>Loading Authorities</title>
|
|
|
+ </section>
|
|
|
+ <section><info><title>Loading Authorities</title></info>
|
|
|
+
|
|
|
<para> How authorities are loaded from groups in the LDAP directory is controlled by the
|
|
|
following attributes. <itemizedlist>
|
|
|
<listitem>
|
|
@@ -109,27 +104,24 @@
|
|
|
</listitem>
|
|
|
<listitem>
|
|
|
<para><literal>group-search-filter</literal>. The filter which is used to
|
|
|
- search for group membership. The default is <literal
|
|
|
- >uniqueMember={0}</literal>, corresponding to the <literal
|
|
|
- >groupOfUniqueMembers</literal> LDAP class. In this case, the
|
|
|
+ search for group membership. The default is <literal>uniqueMember={0}</literal>, corresponding to the <literal>groupOfUniqueMembers</literal> LDAP class. In this case, the
|
|
|
substituted parameter is the full distinguished name of the user. The
|
|
|
parameter <literal>{1}</literal> can be used if you want to filter on
|
|
|
the login name.</para>
|
|
|
</listitem>
|
|
|
</itemizedlist> So if we used the following configuration <programlisting>
|
|
|
- <![CDATA[
|
|
|
- <ldap-authentication-provider user-dn-pattern="uid={0},ou=people group-search-base="ou=groups" />
|
|
|
- ]]></programlisting> and authenticated successfully as user <quote>ben</quote>,
|
|
|
+
|
|
|
+ <ldap-authentication-provider user-dn-pattern="uid={0},ou=people group-search-base="ou=groups" />
|
|
|
+ </programlisting> and authenticated successfully as user <quote>ben</quote>,
|
|
|
the subsequent loading of authorities would perform a search under the directory
|
|
|
entry <literal>ou=groups,dc=springframework,dc=org</literal>, looking for entries
|
|
|
- which contain the attribute <literal>uniqueMember</literal> with value <literal
|
|
|
- >uid=ben,ou=people,dc=springframework,dc=org</literal>. For more information on
|
|
|
+ which contain the attribute <literal>uniqueMember</literal> with value <literal>uid=ben,ou=people,dc=springframework,dc=org</literal>. For more information on
|
|
|
loading authorities, see the Javadoc for the
|
|
|
<classname>DefaultLdapAuthoritiesPopulator</classname> class. </para>
|
|
|
- </sect2>
|
|
|
- </sect1>
|
|
|
- <sect1>
|
|
|
- <title>Implementation Classes</title>
|
|
|
+ </section>
|
|
|
+ </section>
|
|
|
+ <section><info><title>Implementation Classes</title></info>
|
|
|
+
|
|
|
<para>The namespace configuration options we've used above are simple to use and much more
|
|
|
concise than using Spring beans explicitly. There are situations when you may need to
|
|
|
know how to configure Spring Security LDAP directly in your application context. You may
|
|
@@ -146,8 +138,8 @@
|
|
|
<interfacename>LdapAuthoritiesPopulator</interfacename> which are responsible for
|
|
|
authenticating the user and retrieving the user's set of
|
|
|
<interfacename>GrantedAuthority</interfacename>s respectively.</para>
|
|
|
- <sect2 id="ldap-ldap-authenticators">
|
|
|
- <title>LdapAuthenticator Implementations</title>
|
|
|
+ <section xml:id="ldap-ldap-authenticators"><info><title>LdapAuthenticator Implementations</title></info>
|
|
|
+
|
|
|
<para>The authenticator is also responsible for retrieving any required user attributes.
|
|
|
This is because the permissions on the attributes may depend on the type of
|
|
|
authentication being used. For example, if binding as the user, it may be necessary
|
|
@@ -166,8 +158,8 @@
|
|
|
value is never retrieved.</para>
|
|
|
</listitem>
|
|
|
</itemizedlist></para>
|
|
|
- <sect3 id="ldap-ldap-authenticators-common">
|
|
|
- <title>Common Functionality</title>
|
|
|
+ <section xml:id="ldap-ldap-authenticators-common"><info><title>Common Functionality</title></info>
|
|
|
+
|
|
|
<para>Before it is possible to authenticate a user (by either strategy), the
|
|
|
distinguished name (DN) has to be obtained from the login name supplied to the
|
|
|
application. This can be done either by simple pattern-matching (by setting the
|
|
@@ -181,35 +173,34 @@
|
|
|
server</link> for more information on this). For example, if you are using an
|
|
|
LDAP server with the URL <literal>ldap://monkeymachine.co.uk/dc=springframework,dc=org</literal>, and have a
|
|
|
pattern <literal>uid={0},ou=greatapes</literal>, then a login name of "gorilla"
|
|
|
- will map to a DN <literal
|
|
|
- >uid=gorilla,ou=greatapes,dc=springframework,dc=org</literal>. Each configured
|
|
|
+ will map to a DN <literal>uid=gorilla,ou=greatapes,dc=springframework,dc=org</literal>. Each configured
|
|
|
DN pattern will be tried in turn until a match is found. For information on
|
|
|
using a search, see the section on <link linkend="ldap-searchobjects">search
|
|
|
objects</link> below. A combination of the two approaches can also be used -
|
|
|
the patterns will be checked first and if no matching DN is found, the search
|
|
|
will be used.</para>
|
|
|
- </sect3>
|
|
|
- <sect3 id="ldap-ldap-authenticators-bind">
|
|
|
- <title>BindAuthenticator</title>
|
|
|
+ </section>
|
|
|
+ <section xml:id="ldap-ldap-authenticators-bind"><info><title>BindAuthenticator</title></info>
|
|
|
+
|
|
|
<para>The class
|
|
|
<classname>org.springframework.security.providers.ldap.authenticator.BindAuthenticator</classname>
|
|
|
implements the bind authentication strategy. It simply attempts to bind as the
|
|
|
user.</para>
|
|
|
- </sect3>
|
|
|
- <sect3 id="ldap-ldap-authenticators-password">
|
|
|
- <title>PasswordComparisonAuthenticator</title>
|
|
|
+ </section>
|
|
|
+ <section xml:id="ldap-ldap-authenticators-password"><info><title>PasswordComparisonAuthenticator</title></info>
|
|
|
+
|
|
|
<para>The class
|
|
|
<classname>org.springframework.security.providers.ldap.authenticator.PasswordComparisonAuthenticator</classname>
|
|
|
implements the password comparison authentication strategy.</para>
|
|
|
- </sect3>
|
|
|
- <sect3 id="ldap-ldap-authenticators-active-directory">
|
|
|
- <title>Active Directory Authentication</title>
|
|
|
+ </section>
|
|
|
+ <section xml:id="ldap-ldap-authenticators-active-directory"><info><title>Active Directory Authentication</title></info>
|
|
|
+
|
|
|
<para>In addition to standard LDAP authentication (binding with a DN), Active
|
|
|
Directory has its own non-standard syntax for user authentication.</para>
|
|
|
- </sect3>
|
|
|
- </sect2>
|
|
|
- <sect2 id="ldap-context-source">
|
|
|
- <title>Connecting to the LDAP Server</title>
|
|
|
+ </section>
|
|
|
+ </section>
|
|
|
+ <section xml:id="ldap-context-source"><info><title>Connecting to the LDAP Server</title></info>
|
|
|
+
|
|
|
<para>The beans discussed above have to be able to connect to the server. They both have
|
|
|
to be supplied with a <interfacename>SpringSecurityContextSource</interfacename>
|
|
|
which is an extension of Spring LDAP's <interfacename>ContextSource</interfacename>.
|
|
@@ -220,59 +211,54 @@
|
|
|
server (instead of binding anonymously). For more information read the Javadoc for
|
|
|
this class and for Spring LDAP's <classname>AbstractContextSource</classname>.
|
|
|
</para>
|
|
|
- </sect2>
|
|
|
- <sect2 id="ldap-searchobjects">
|
|
|
- <title>LDAP Search Objects</title>
|
|
|
+ </section>
|
|
|
+ <section xml:id="ldap-searchobjects"><info><title>LDAP Search Objects</title></info>
|
|
|
+
|
|
|
<para>Often more a more complicated strategy than simple DN-matching is required to
|
|
|
locate a user entry in the directory. This can be encapsulated in an
|
|
|
<interfacename>LdapUserSearch</interfacename> instance which can be supplied to
|
|
|
the authenticator implementations, for example, to allow them to locate a user. The
|
|
|
supplied implementation is <classname>FilterBasedLdapUserSearch</classname>.</para>
|
|
|
- <sect3 id="ldap-searchobjects-filter">
|
|
|
- <title id="ldap-searchobjects-filter-based"
|
|
|
- ><classname>FilterBasedLdapUserSearch</classname></title>
|
|
|
+ <section xml:id="ldap-searchobjects-filter"><info><title xml:id="ldap-searchobjects-filter-based"><classname>FilterBasedLdapUserSearch</classname></title></info>
|
|
|
+
|
|
|
<para>This bean uses an LDAP filter to match the user object in the directory. The
|
|
|
process is explained in the Javadoc for the corresponding search method on the
|
|
|
- <ulink
|
|
|
- url="http://java.sun.com/j2se/1.4.2/docs/api/javax/naming/directory/DirContext.html#search(javax.naming.Name,%20java.lang.String,%20java.lang.Object[],%20javax.naming.directory.SearchControls)"
|
|
|
- >JDK DirContext class</ulink>. As explained there, the search filter can be
|
|
|
- supplied with parameters. For this class, the only valid parameter is <parameter
|
|
|
- >{0}</parameter> which will be replaced with the user's login name.</para>
|
|
|
- </sect3>
|
|
|
- </sect2>
|
|
|
- <sect2 id="ldap-bean-config">
|
|
|
- <title>Spring Bean Configuration</title>
|
|
|
+ <link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://java.sun.com/j2se/1.4.2/docs/api/javax/naming/directory/DirContext.html#search(javax.naming.Name,%20java.lang.String,%20java.lang.Object[],%20javax.naming.directory.SearchControls)">JDK DirContext class</link>. As explained there, the search filter can be
|
|
|
+ supplied with parameters. For this class, the only valid parameter is <parameter>{0}</parameter> which will be replaced with the user's login name.</para>
|
|
|
+ </section>
|
|
|
+ </section>
|
|
|
+ <section xml:id="ldap-bean-config"><info><title>Spring Bean Configuration</title></info>
|
|
|
+
|
|
|
<para>A typical configuration, using some of the beans we've discussed here, might look
|
|
|
like this: <programlisting>
|
|
|
- <![CDATA[
|
|
|
-<bean id="contextSource"
|
|
|
- class="org.springframework.security.ldap.DefaultSpringSecurityContextSource">
|
|
|
- <constructor-arg value="ldap://monkeymachine:389/dc=springframework,dc=org"/>
|
|
|
- <property name="userDn" value="cn=manager,dc=springframework,dc=org"/>
|
|
|
- <property name="password" value="password"/>
|
|
|
-</bean>
|
|
|
+
|
|
|
+<bean id="contextSource"
|
|
|
+ class="org.springframework.security.ldap.DefaultSpringSecurityContextSource">
|
|
|
+ <constructor-arg value="ldap://monkeymachine:389/dc=springframework,dc=org"/>
|
|
|
+ <property name="userDn" value="cn=manager,dc=springframework,dc=org"/>
|
|
|
+ <property name="password" value="password"/>
|
|
|
+</bean>
|
|
|
|
|
|
-<bean id="ldapAuthProvider"
|
|
|
- class="org.springframework.security.providers.ldap.LdapAuthenticationProvider">
|
|
|
- <constructor-arg>
|
|
|
- <bean class="org.springframework.security.providers.ldap.authenticator.BindAuthenticator">
|
|
|
- <constructor-arg ref="contextSource"/>
|
|
|
- <property name="userDnPatterns"><list><value>uid={0},ou=people</value></list></property>
|
|
|
- </bean>
|
|
|
- </constructor-arg>
|
|
|
- <constructor-arg>
|
|
|
- <bean class="org.springframework.security.ldap.populator.DefaultLdapAuthoritiesPopulator">
|
|
|
- <constructor-arg ref="contextSource"/>
|
|
|
- <constructor-arg value="ou=groups"/>
|
|
|
- <property name="groupRoleAttribute" value="ou"/>
|
|
|
- </bean>
|
|
|
- </constructor-arg>
|
|
|
-</bean>
|
|
|
-]]>
|
|
|
+<bean id="ldapAuthProvider"
|
|
|
+ class="org.springframework.security.providers.ldap.LdapAuthenticationProvider">
|
|
|
+ <constructor-arg>
|
|
|
+ <bean class="org.springframework.security.providers.ldap.authenticator.BindAuthenticator">
|
|
|
+ <constructor-arg ref="contextSource"/>
|
|
|
+ <property name="userDnPatterns"><list><value>uid={0},ou=people</value></list></property>
|
|
|
+ </bean>
|
|
|
+ </constructor-arg>
|
|
|
+ <constructor-arg>
|
|
|
+ <bean class="org.springframework.security.ldap.populator.DefaultLdapAuthoritiesPopulator">
|
|
|
+ <constructor-arg ref="contextSource"/>
|
|
|
+ <constructor-arg value="ou=groups"/>
|
|
|
+ <property name="groupRoleAttribute" value="ou"/>
|
|
|
+ </bean>
|
|
|
+ </constructor-arg>
|
|
|
+</bean>
|
|
|
+
|
|
|
</programlisting> This would set up the provider to access an LDAP server with URL
|
|
|
<literal>ldap://monkeymachine:389/dc=springframework,dc=org</literal>.
|
|
|
- Authentication will be performed by attempting to bind with the DN <literal
|
|
|
- >uid=<user-login-name>,ou=people,dc=springframework,dc=org</literal>. After
|
|
|
+ Authentication will be performed by attempting to bind with the DN <literal>uid=<user-login-name>,ou=people,dc=springframework,dc=org</literal>. After
|
|
|
successful authentication, roles will be assigned to the user by searching under the DN
|
|
|
<literal>ou=groups,dc=springframework,dc=org</literal> with the default filter
|
|
|
<literal>(member=<user's-DN>)</literal>. The role name will be taken from the
|
|
@@ -280,18 +266,18 @@
|
|
|
<para>To configurae a user search object, which uses the filter
|
|
|
<literal>(uid=<user-login-name>)</literal> for use instead of the
|
|
|
DN-pattern (or in addition to it), you would configure the following bean
|
|
|
- <programlisting><![CDATA[
|
|
|
-<bean id="userSearch"
|
|
|
- class="org.springframework.security.ldap.search.FilterBasedLdapUserSearch">
|
|
|
- <constructor-arg index="0" value=""/>
|
|
|
- <constructor-arg index="1" value="(uid={0})"/>
|
|
|
- <constructor-arg index="2" ref="contextSource" />
|
|
|
- <property name="searchSubtree" value="true"/>
|
|
|
-</bean> ]]>
|
|
|
+ <programlisting>
|
|
|
+<bean id="userSearch"
|
|
|
+ class="org.springframework.security.ldap.search.FilterBasedLdapUserSearch">
|
|
|
+ <constructor-arg index="0" value=""/>
|
|
|
+ <constructor-arg index="1" value="(uid={0})"/>
|
|
|
+ <constructor-arg index="2" ref="contextSource" />
|
|
|
+ <property name="searchSubtree" value="true"/>
|
|
|
+</bean>
|
|
|
</programlisting>
|
|
|
and use it by setting the authenticator's <property>userSearch</property> property. The authenticator
|
|
|
would then call the search object to obtain the correct user's DN before attempting to bind as this user.</para>
|
|
|
- </sect2>
|
|
|
- </sect1>
|
|
|
+ </section>
|
|
|
+ </section>
|
|
|
|
|
|
-</chapter>
|
|
|
+</chapter>
|