|
|
|
|
@ -15,9 +15,11 @@
@@ -15,9 +15,11 @@
|
|
|
|
|
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: |
|
|
|
|
<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 |
|
|
|
|
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> |
|
|
|
|
@ -26,122 +28,89 @@
@@ -26,122 +28,89 @@
|
|
|
|
|
<info> |
|
|
|
|
<title>Using LDAP with Spring Security</title> |
|
|
|
|
</info> |
|
|
|
|
<para> |
|
|
|
|
LDAP authentication in Spring Security can be roughly divided into the following stages. |
|
|
|
|
<orderedlist inheritnum="ignore" continuation="restarts"> |
|
|
|
|
<para> LDAP authentication in Spring Security can be roughly divided into the following |
|
|
|
|
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, unless the exact mapping of |
|
|
|
|
usernames to DNs is known in advance.</para> |
|
|
|
|
<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, |
|
|
|
|
unless the exact mapping of usernames to DNs is known in advance.</para> |
|
|
|
|
</listitem> |
|
|
|
|
<listitem> |
|
|
|
|
<para>Authenticating the user, either by binding as that user or by performing a |
|
|
|
|
remote |
|
|
|
|
<quote>compare</quote> |
|
|
|
|
operation of the user's password against the password attribute in the |
|
|
|
|
directory entry for the DN.</para> |
|
|
|
|
remote <quote>compare</quote> operation of the user's password against the |
|
|
|
|
password attribute in the directory entry for the DN.</para> |
|
|
|
|
</listitem> |
|
|
|
|
<listitem> |
|
|
|
|
<para>Loading the list of authorities for the user.</para> |
|
|
|
|
</listitem> |
|
|
|
|
</orderedlist> |
|
|
|
|
The exception is when the LDAP directory is just being used to retrieve user information |
|
|
|
|
and authenticate against it locally. This may not be possible as directories are often |
|
|
|
|
set up with limited read access for attributes such as user passwords. |
|
|
|
|
</para> |
|
|
|
|
<para> |
|
|
|
|
We will look at some configuration scenarios below. For full information on available |
|
|
|
|
</orderedlist> The exception is when the LDAP directory is just being used to retrieve |
|
|
|
|
user information and authenticate against it locally. This may not be possible as |
|
|
|
|
directories are often set up with limited read access for attributes such as user |
|
|
|
|
passwords. </para> |
|
|
|
|
<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> |
|
|
|
|
which should be available in your XML editor). </para> |
|
|
|
|
</section> |
|
|
|
|
<section xml:id="ldap-server"> |
|
|
|
|
<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[ |
|
|
|
|
<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> |
|
|
|
|
</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[ |
|
|
|
|
<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 |
|
|
|
|
<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 |
|
|
|
|
</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[ |
|
|
|
|
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 |
|
|
|
|
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 |
|
|
|
|
]]></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 LDAP sample application. |
|
|
|
|
</para> |
|
|
|
|
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[ |
|
|
|
|
<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 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[ |
|
|
|
|
]]></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 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> |
|
|
|
|
]]></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> |
|
|
|
|
</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> |
|
|
|
|
<para> How authorities are loaded from groups in the LDAP directory is controlled by the |
|
|
|
|
following attributes. <itemizedlist> |
|
|
|
|
<listitem> |
|
|
|
|
<para> |
|
|
|
|
<literal>group-search-base</literal>. Defines the part of the directory |
|
|
|
|
@ -151,39 +120,32 @@
@@ -151,39 +120,32 @@
|
|
|
|
|
<para> |
|
|
|
|
<literal>group-role-attribute</literal>. The attribute which contains |
|
|
|
|
the name of the authority defined by the group entry. Defaults to |
|
|
|
|
<literal>cn</literal> |
|
|
|
|
<literal>cn</literal> |
|
|
|
|
</para> |
|
|
|
|
</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 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> |
|
|
|
|
<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[ |
|
|
|
|
</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>, 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>. |
|
|
|
|
By default the authority names will have the prefix <literal>ROLE_</literal> prepended. You can |
|
|
|
|
change this using the <literal>role-prefix</literal> attribute. If you don't want any prefix, use |
|
|
|
|
<literal>role-prefix="none"</literal>. For more information |
|
|
|
|
on loading authorities, see the Javadoc for the |
|
|
|
|
<classname>DefaultLdapAuthoritiesPopulator</classname> |
|
|
|
|
class. |
|
|
|
|
</para> |
|
|
|
|
]]></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>. By default the |
|
|
|
|
authority names will have the prefix <literal>ROLE_</literal> prepended. You can |
|
|
|
|
change this using the <literal>role-prefix</literal> attribute. If you don't want |
|
|
|
|
any prefix, use <literal>role-prefix="none"</literal>. For more information on |
|
|
|
|
loading authorities, see the Javadoc for the |
|
|
|
|
<classname>DefaultLdapAuthoritiesPopulator</classname> class. </para> |
|
|
|
|
</section> |
|
|
|
|
</section> |
|
|
|
|
<section> |
|
|
|
|
@ -194,16 +156,13 @@
@@ -194,16 +156,13 @@
|
|
|
|
|
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 |
|
|
|
|
wish to customize the behaviour of some of the classes, for example. If you're happy |
|
|
|
|
using namespace configuration then you can skip this section and the next one. |
|
|
|
|
</para> |
|
|
|
|
<para> |
|
|
|
|
The main LDAP provider class, <classname>LdapAuthenticationProvider</classname>, |
|
|
|
|
using namespace configuration then you can skip this section and the next one. </para> |
|
|
|
|
<para> The main LDAP provider class, <classname>LdapAuthenticationProvider</classname>, |
|
|
|
|
doesn't actually do much itself but delegates the work to two other beans, an |
|
|
|
|
<interfacename>LdapAuthenticator</interfacename> |
|
|
|
|
and an |
|
|
|
|
<interfacename>LdapAuthoritiesPopulator</interfacename> |
|
|
|
|
which are responsible for authenticating the user and retrieving the user's set of |
|
|
|
|
<interfacename>GrantedAuthority</interfacename>s respectively.</para> |
|
|
|
|
<interfacename>LdapAuthenticator</interfacename> and an |
|
|
|
|
<interfacename>LdapAuthoritiesPopulator</interfacename> which are responsible for |
|
|
|
|
authenticating the user and retrieving the user's set of |
|
|
|
|
<interfacename>GrantedAuthority</interfacename>s respectively.</para> |
|
|
|
|
<section xml:id="ldap-ldap-authenticators"> |
|
|
|
|
<info> |
|
|
|
|
<title>LdapAuthenticator Implementations</title> |
|
|
|
|
@ -212,10 +171,10 @@
@@ -212,10 +171,10 @@
|
|
|
|
|
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 |
|
|
|
|
to read them with the user's own permissions.</para> |
|
|
|
|
<para>There are currently two authentication strategies supplied with Spring Security: |
|
|
|
|
<itemizedlist> |
|
|
|
|
<para>There are currently two authentication strategies supplied with Spring Security: <itemizedlist> |
|
|
|
|
<listitem> |
|
|
|
|
<para>Authentication directly to the LDAP server ("bind" authentication).</para> |
|
|
|
|
<para>Authentication directly to the LDAP server ("bind" |
|
|
|
|
authentication).</para> |
|
|
|
|
</listitem> |
|
|
|
|
<listitem> |
|
|
|
|
<para>Password comparison, where the password supplied by the user is |
|
|
|
|
@ -225,8 +184,7 @@
@@ -225,8 +184,7 @@
|
|
|
|
|
password is passed to the server for comparison and the real password |
|
|
|
|
value is never retrieved.</para> |
|
|
|
|
</listitem> |
|
|
|
|
</itemizedlist> |
|
|
|
|
</para> |
|
|
|
|
</itemizedlist></para> |
|
|
|
|
<section xml:id="ldap-ldap-authenticators-common"> |
|
|
|
|
<info> |
|
|
|
|
<title>Common Functionality</title> |
|
|
|
|
@ -234,35 +192,31 @@
@@ -234,35 +192,31 @@
|
|
|
|
|
<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 |
|
|
|
|
<property>setUserDnPatterns</property> |
|
|
|
|
array property) or by setting the |
|
|
|
|
<property>userSearch</property> |
|
|
|
|
property. For the DN pattern-matching approach, a standard Java pattern format |
|
|
|
|
is used, and the login name will be substituted for the parameter |
|
|
|
|
<parameter>{0}</parameter>. The pattern should be relative to the DN that the |
|
|
|
|
configured |
|
|
|
|
<interfacename>SpringSecurityContextSource</interfacename> |
|
|
|
|
will bind to (see the section on |
|
|
|
|
<link linkend="ldap-context-source">connecting to the LDAP 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 |
|
|
|
|
<property>setUserDnPatterns</property> array property) or by setting the |
|
|
|
|
<property>userSearch</property> property. For the DN pattern-matching |
|
|
|
|
approach, a standard Java pattern format is used, and the login name will be |
|
|
|
|
substituted for the parameter <parameter>{0}</parameter>. The pattern should be |
|
|
|
|
relative to the DN that the configured |
|
|
|
|
<interfacename>SpringSecurityContextSource</interfacename> will bind to (see |
|
|
|
|
the section on <link linkend="ldap-context-source">connecting to the LDAP |
|
|
|
|
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 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> |
|
|
|
|
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> |
|
|
|
|
</section> |
|
|
|
|
<section xml:id="ldap-ldap-authenticators-bind"> |
|
|
|
|
<info> |
|
|
|
|
<title>BindAuthenticator</title> |
|
|
|
|
</info> |
|
|
|
|
<para>The class <classname>BindAuthenticator</classname> in the package |
|
|
|
|
<filename>org.springframework.security.ldap.authentication</filename> |
|
|
|
|
<filename>org.springframework.security.ldap.authentication</filename> |
|
|
|
|
implements the bind authentication strategy. It simply attempts to bind as the |
|
|
|
|
user.</para> |
|
|
|
|
</section> |
|
|
|
|
@ -270,8 +224,8 @@
@@ -270,8 +224,8 @@
|
|
|
|
|
<info> |
|
|
|
|
<title>PasswordComparisonAuthenticator</title> |
|
|
|
|
</info> |
|
|
|
|
<para>The class <classname>PasswordComparisonAuthenticator</classname> |
|
|
|
|
implements the password comparison authentication strategy.</para> |
|
|
|
|
<para>The class <classname>PasswordComparisonAuthenticator</classname> implements |
|
|
|
|
the password comparison authentication strategy.</para> |
|
|
|
|
</section> |
|
|
|
|
<section xml:id="ldap-ldap-authenticators-active-directory"> |
|
|
|
|
<info> |
|
|
|
|
@ -286,17 +240,14 @@
@@ -286,17 +240,14 @@
|
|
|
|
|
<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>. Unless you have special requirements, |
|
|
|
|
you will usually configure a |
|
|
|
|
<classname>DefaultSpringSecurityContextSource</classname> |
|
|
|
|
bean, which can be configured with the URL of your LDAP server and optionally with |
|
|
|
|
the username and password of a "manager" user which will be used by default when |
|
|
|
|
binding to the server (instead of binding anonymously). For more information read |
|
|
|
|
the Javadoc for this class and for Spring LDAP's |
|
|
|
|
<classname>AbstractContextSource</classname>. |
|
|
|
|
to be supplied with a <interfacename>SpringSecurityContextSource</interfacename> |
|
|
|
|
which is an extension of Spring LDAP's <interfacename>ContextSource</interfacename>. |
|
|
|
|
Unless you have special requirements, you will usually configure a |
|
|
|
|
<classname>DefaultSpringSecurityContextSource</classname> bean, which can be |
|
|
|
|
configured with the URL of your LDAP server and optionally with the username and |
|
|
|
|
password of a "manager" user which will be used by default when binding to the |
|
|
|
|
server (instead of binding anonymously). For more information read the Javadoc for |
|
|
|
|
this class and for Spring LDAP's <classname>AbstractContextSource</classname>. |
|
|
|
|
</para> |
|
|
|
|
</section> |
|
|
|
|
<section xml:id="ldap-searchobjects"> |
|
|
|
|
@ -305,10 +256,9 @@
@@ -305,10 +256,9 @@
|
|
|
|
|
</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> |
|
|
|
|
<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> |
|
|
|
|
<section xml:id="ldap-searchobjects-filter"> |
|
|
|
|
<info> |
|
|
|
|
<title xml:id="ldap-searchobjects-filter-based"> |
|
|
|
|
@ -317,33 +267,35 @@
@@ -317,33 +267,35 @@
|
|
|
|
|
</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 |
|
|
|
|
<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> |
|
|
|
|
<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-authorities"> |
|
|
|
|
<title>LdapAuthoritiesPopulator</title> |
|
|
|
|
<para> |
|
|
|
|
After authenticating the user successfully, the <classname>LdapAuthenticationProvider</classname> |
|
|
|
|
will attempt to load a set of authorities for the user by calling the configured |
|
|
|
|
<interfacename>LdapAuthoritiesPopulator</interfacename> bean. The <classname>DefaultLdapAuthoritiesPopulator</classname> |
|
|
|
|
is an implementation which will load the authorities by searching the directory for groups of which the user is a member |
|
|
|
|
(typically these will be <literal>groupOfNames</literal> or <literal>groupOfUniqueNames</literal> entries in the directory). |
|
|
|
|
Consult the Javadoc for this class for more details on how it works. |
|
|
|
|
</para> |
|
|
|
|
<para>If you want to use LDAP only for authentication, but load the authorities from a difference source (such as a database) |
|
|
|
|
then you can provide your own implementation of this interface and inject that instead.</para> |
|
|
|
|
<para> After authenticating the user successfully, the |
|
|
|
|
<classname>LdapAuthenticationProvider</classname> will attempt to load a set of |
|
|
|
|
authorities for the user by calling the configured |
|
|
|
|
<interfacename>LdapAuthoritiesPopulator</interfacename> bean. The |
|
|
|
|
<classname>DefaultLdapAuthoritiesPopulator</classname> is an implementation |
|
|
|
|
which will load the authorities by searching the directory for groups of which the |
|
|
|
|
user is a member (typically these will be <literal>groupOfNames</literal> or |
|
|
|
|
<literal>groupOfUniqueNames</literal> entries in the directory). Consult the |
|
|
|
|
Javadoc for this class for more details on how it works. </para> |
|
|
|
|
<para>If you want to use LDAP only for authentication, but load the authorities from a |
|
|
|
|
difference source (such as a database) then you can provide your own implementation |
|
|
|
|
of this interface and inject that instead.</para> |
|
|
|
|
</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[ |
|
|
|
|
like this: <programlisting><![CDATA[ |
|
|
|
|
<bean id="contextSource" |
|
|
|
|
class="org.springframework.security.ldap.DefaultSpringSecurityContextSource"> |
|
|
|
|
<constructor-arg value="ldap://monkeymachine:389/dc=springframework,dc=org"/> |
|
|
|
|
@ -370,68 +322,61 @@
@@ -370,68 +322,61 @@
|
|
|
|
|
</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>. |
|
|
|
|
</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>. |
|
|
|
|
<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 |
|
|
|
|
<quote>ou</quote> |
|
|
|
|
attribute of each match.</para> |
|
|
|
|
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 <quote>ou</quote> attribute of each match.</para> |
|
|
|
|
<para>To configure 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[ |
|
|
|
|
<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" /> |
|
|
|
|
</bean> ]]> |
|
|
|
|
</programlisting> |
|
|
|
|
and use it by setting the <classname>BindAuthenticator</classname> bean's |
|
|
|
|
<property>userSearch</property> |
|
|
|
|
</programlisting> and use it by setting the |
|
|
|
|
<classname>BindAuthenticator</classname> bean'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> |
|
|
|
|
</section> |
|
|
|
|
<section xml:id="ldap-custom-user-details"> |
|
|
|
|
<title>LDAP Attributes and Customized UserDetails</title> |
|
|
|
|
<para> |
|
|
|
|
The net result of an authentication using <classname>LdapAuthenticationProvider</classname> is the |
|
|
|
|
same as a normal Spring Security authentication using the standard <interfacename>UserDetailsService</interfacename> |
|
|
|
|
interface. A <interfacename>UserDetails</interfacename> object is created and stored in the |
|
|
|
|
returned <interfacename>Authentication</interfacename> object. As with using a |
|
|
|
|
<interfacename>UserDetailsService</interfacename>, a common requirement is to be able to customize this |
|
|
|
|
implementation and add extra properties. When using LDAP, these will normally be attributes from the user entry. |
|
|
|
|
The creation of the <interfacename>UserDetails</interfacename> object is controlled by the provider's |
|
|
|
|
<interfacename>UserDetailsContextMapper</interfacename> strategy, which is responsible for mapping user objects |
|
|
|
|
to and from LDAP context data: |
|
|
|
|
<programlisting><![CDATA[ |
|
|
|
|
<para> The net result of an authentication using |
|
|
|
|
<classname>LdapAuthenticationProvider</classname> is the same as a normal Spring |
|
|
|
|
Security authentication using the standard |
|
|
|
|
<interfacename>UserDetailsService</interfacename> interface. A |
|
|
|
|
<interfacename>UserDetails</interfacename> object is created and stored in the |
|
|
|
|
returned <interfacename>Authentication</interfacename> object. As with using a |
|
|
|
|
<interfacename>UserDetailsService</interfacename>, a common requirement is to be |
|
|
|
|
able to customize this implementation and add extra properties. When using LDAP, |
|
|
|
|
these will normally be attributes from the user entry. The creation of the |
|
|
|
|
<interfacename>UserDetails</interfacename> object is controlled by the |
|
|
|
|
provider's <interfacename>UserDetailsContextMapper</interfacename> strategy, which |
|
|
|
|
is responsible for mapping user objects to and from LDAP context data: <programlisting><![CDATA[ |
|
|
|
|
public interface UserDetailsContextMapper { |
|
|
|
|
UserDetails mapUserFromContext(DirContextOperations ctx, String username, |
|
|
|
|
GrantedAuthority[] authority); |
|
|
|
|
Collection<GrantedAuthority> authorities); |
|
|
|
|
|
|
|
|
|
void mapUserToContext(UserDetails user, DirContextAdapter ctx); |
|
|
|
|
}]]> |
|
|
|
|
</programlisting> |
|
|
|
|
Only the first method is relevant for authentication. If you provide an implementation of this interface, you can |
|
|
|
|
control exactly how the UserDetails object is created. The first parameter is an instance of Spring LDAP's |
|
|
|
|
<interfacename>DirContextOperations</interfacename> which gives you access to the LDAP attributes which were loaded. |
|
|
|
|
The <literal>username</literal> parameter is the name used to authenticate and the final parameter is the list of authorities |
|
|
|
|
loaded for the user. |
|
|
|
|
</para> |
|
|
|
|
<para> |
|
|
|
|
The way the context data is loaded varies slightly depending on the type of authentication you are using. With the |
|
|
|
|
<classname>BindAuthenticatior</classname>, the context returned from the bind operation will be used to read the attributes, |
|
|
|
|
otherwise the data will be read using the standard context obtained from the configured |
|
|
|
|
<interfacename>ContextSource</interfacename> (when a search is configured to locate the user, |
|
|
|
|
this will be the data returned by the search object). |
|
|
|
|
</para> |
|
|
|
|
</programlisting> Only the first method is relevant for |
|
|
|
|
authentication. If you provide an implementation of this interface, you can control |
|
|
|
|
exactly how the UserDetails object is created. The first parameter is an instance of |
|
|
|
|
Spring LDAP's <interfacename>DirContextOperations</interfacename> which gives you |
|
|
|
|
access to the LDAP attributes which were loaded. The <literal>username</literal> |
|
|
|
|
parameter is the name used to authenticate and the final parameter is the collection |
|
|
|
|
of authorities loaded for the user. </para> |
|
|
|
|
<para> The way the context data is loaded varies slightly depending on the type of |
|
|
|
|
authentication you are using. With the <classname>BindAuthenticatior</classname>, |
|
|
|
|
the context returned from the bind operation will be used to read the attributes, |
|
|
|
|
otherwise the data will be read using the standard context obtained from the |
|
|
|
|
configured <interfacename>ContextSource</interfacename> (when a search is configured |
|
|
|
|
to locate the user, this will be the data returned by the search object). </para> |
|
|
|
|
</section> |
|
|
|
|
</section> |
|
|
|
|
</chapter> |
|
|
|
|
</chapter> |
|
|
|
|
|