Configuring LDAP-based security

LDAP is a popular protocol used to host user accounts and group associations as well. Spring Python provides a convenient LdapAuthenticationProvider with flexible options to support conventional schemas as well as custom ones.

Note

At the time of writing, Spring Python LDAP only works on CPython and not on Jython.

LdapAuthenticationProvider has two components:

  • A BindAuthenticator and a PasswordComparisonAuthenticator to perform authentication
  • A DefaultLdapAuthoritiesPopulator to lookup granted authorities based on conventional LDAP group associations

LDAP supports binding, where the server confirms the user's password. BindAuthenticator utilizes this feature to confirm the user's password.

It is also possible to fetch the password from the directory server, and do a password comparison after properly hashing the user's password. PasswordComparisonAuthenticator is used to perform this operation.

After confirming a user's credentials, the second step of LdapAuthenticationProvider is to search the directory for groups the user is associated with.

The following code shows an application context where LdapAuthenticationProvider is set up with a BindAuthenticator and an authorities populator.

from springpython.config import PythonConfig
from springpython.config import Object
from springpython.security.providers.Ldap import *
class LdapAppContext(PythonConfig):
def __init__(self):
super(LdapAppContext, self).__init__()
@Object
def auth_manager(self):
auth_manager = AuthenticationManager()
auth_manager.auth_providers = [self.auth_provider()]
return auth_manager
@Object
def auth_provider(self):
provider = LdapAuthenticationProvider()
provider.ldap_authenticator = self.authenticator()
provider.ldap_authorities_populator =
self.authorities_populator()
return provider
@Object
def context(self):
return DefaultSpringSecurityContextSource(
url="ldap://localhost:53389/dc=springpythonbook,dc=com")
@Object
def authenticator(self):
return BindAuthenticator(
context_source=self.context(),
user_dn_patterns="uid={0},ou=people")
@Object
def authorities_populator(self):
return DefaultLdapAuthoritiesPopulator(
context_source=self.context(),
group_search_base="ou=groups")
  • All the LDAP components are pointed at one directory server, with the format ldap://<server>:<port>/<baseDN>
  • BindAuthenticator is configured to search recursively from the<baseDN> with the pattern uid={0},ou=people, where {0} is where the supplied username will be substituted. When the dn is found, a bind is performed using the supplied password
  • DefaultLdapAuthoritiesPopulator will search one level below baseDN at ou=groups, looking for any entries that have a member attribute pointed at the user's dn. It is possible to override group_search_filter with something else like uniqueMember={0}, if the directory schema is different. By default, the name of the group fetched will be the group's cn. Overriding group_role_attr allows picking another attribute. By default, the group name will be converted to upper case, and prefixed with ROLE_. These can be overridden with role_prefix and convert_to_upper

    To do a password check instead, replace BindAuthenticator with PasswordComparisonAuthenticator

  • By default it supports both plain text passwords as well as SHA hashed ones that are base64 encoded. This can be overridden by supplying an alternative password encoder to encoder attribute
  • It has the same constructor arguments as BindAuthenticator, meaning you can specify user_dn_patterns
  • By default, it looks for the password stored in the userPassword attribute. You can override this by setting the password_attr_name attribute

If you have a non-conventional usage of either password authentication, or group management, you can plug in your own authenticator or authorities populator. I ran into this problem myself when a legacy system stored the roles in a custom attribute inside the user's record instead of a separate group.

With all the options to override the defaults, it should be pretty easy to get LDAP security management underway.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.138.204.195