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.
LdapAuthenticationProvider
has two components:
BindAuthenticator
and a PasswordComparisonAuthenticator
to perform authenticationDefaultLdapAuthoritiesPopulator
to lookup granted authorities based on conventional LDAP group associationsLDAP 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")
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 passwordDefaultLdapAuthoritiesPopulator
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
encoder
attribute BindAuthenticator
, meaning you can specify user_dn_patterns
userPassword
attribute. You can override this by setting the password_attr_name
attributeIf 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.
3.138.204.195