Using multiple security providers is easy

Supporting multiple security providers is a valuable feature. There are several common use cases where this is quite beneficial.

  • Migrating from an old security solution to a new one—This is where started with security provider, but need to migrate to another one. For example, we started with user accounts stored in the database, but want to move to a two-factor authentication system.
  • Supporting multiple user communities—This is where two different sites running on two different servers are merged to run on a single server. Instead of maintaining two different applications, we want to consolidate the data but maintain existing roles and accounts.
  • Providing redundant security access—This is when we need to have multiple security providers to handle failures and maintenance windows.

Let's explore these scenarios in more detail.

Migrating from an old security solution to a new one

One very handy use case is where you want to migrate users from an old login system to a new one. For example, your project may have several tools that have all been using their own custom database solution. However, you finally want to centralize everyone's details in a common LDAP server. With both systems keyed up, as new users are issued new credentials, they can log in with no interruption of service. Once everyone has been migrated, you can remove the old security provider.

It also makes it easy to have redundant security providers, such as having more than one LDAP URL to point at.

Earlier, we saw the configuration for an AuthenticationManager that looked like this:

@Object
def auth_manager(self):
auth_manager = AuthenticationManager()
auth_manager.auth_providers = [self.auth_provider()]
return auth_manager

AuthenticationManager supports a list of providers. It will iterate over each one until a successful match is made. To support the migration use case, it can be altered to look like this:

@Object
def auth_manager(self):
auth_manager = AuthenticationManager()
auth_manager.auth_providers = [
self.old_auth_provider(),
self.new_auth_provider()]
return auth_manager

With this setup, our system will first try to use the old authentication provider. However, if it fails, Spring Python Security will try the new authentication provider.

Supporting multiple user communities

It is possible our application may have to support multiple users. Imagine we had developed our application and had complete Spring Python Security configuration as well, handling users based on a DatabaseUserDetailsService. Some time after that, our company acquires another company, bringing on board many new employees that need access to the system. It might be too much effort to migrate them into the new system. Or at least, it might be too expensive. Instead, it would be much easier to configure another authentication provider to point at their current system. The only other feature needed would be to add the extra roles from the new users to the access decision manager.

The solution would look much like the previous use case. The company can now easily decide whether to continue in this fashion, or start a migration of the new users into the already existing system as shown in the previous use case.

Providing redundant security access

We just recently walked through configuring security access to an LDAP server. In the current version of Spring Python, it only supports one URL. To handle two LDAP servers in a redundant solution, all you have to do is configure two instances of each and then plug them in to the AuthenticationManager.

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_provider1(),
self.auth_provider2()]
return auth_manager
@Object
def auth_provider1(self):
provider = LdapAuthenticationProvider()
provider.ldap_authenticator = self.authenticator1()
provider.ldap_authorities_populator =
self.authorities_populator1()
return provider
@Object
def auth_provider2(self):
provider = LdapAuthenticationProvider()
provider.ldap_authenticator = self.authenticator2()
provider.ldap_authorities_populator =
self.authorities_populator2()
return provider
@Object
def context1(self):
return DefaultSpringSecurityContextSource(
url="ldap://server1:53389/dc=springpythonbook,dc=com")
@Object
def context2(self):
return DefaultSpringSecurityContextSource(
url="ldap://server2:53389/dc=springpythonbook,dc=com")
@Object
def authenticator1(self):
return BindAuthenticator(
context_source=self.context1(),
user_dn_patterns="uid={0},ou=people")
@Object
def authenticator2(self):
return BindAuthenticator(
context_source=self.context2(),
user_dn_patterns="uid={0},ou=people")
@Object
def authorities_populator1(self):
return DefaultLdapAuthoritiesPopulator(
context_source=self.context1(),
group_search_base="ou=groups")
@Object
def authorities_populator2(self):
return DefaultLdapAuthoritiesPopulator(
context_source=self.context2(),
group_search_base="ou=groups")

While it is possible Spring Python will eventually support multiple URLs, the ability to combine existing components gives you an already working solution right now.

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

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