We are working on project that has multiple administrative domains. Our planned approach is to decorate AuthenticationProviders with a regular expression based domain matcher. Users use an email style username. We plan to use the information in the username to determine which AuthenticationProvider should be used. Then we map the username to the format required by the underlying AuthenticationProvider (and user store).
I believe this approach should work with DaoAuthenticationProvider.
Questions:
1. Are we making a new wheel or is similar functionality already part of Acegi? Without additional code?
2. Does this seem like a reasonable approach to the Acegi experts?
Feedback is appreciated.
The Spring context will look something like this:
Code:
<bean id="department1AuthenticationProvider"
class="RegexMatchingProvider" />
<constructor-arg>
<ref local=" department1DaoAuthenticationProvider"/>
</constructor-arg>
<property name="domainRegex">
<value>\w+@department1.company.com</value>
</property>
<property name="usernameRegex">
<value>(\w+)@department1.company.com</value>
</property>
<property name="usernameReplacement">
<value>$1</value>
</property>
</bean>
<bean id="department2AuthenticationProvider"
class="RegexMatchingProvider" />
<constructor-arg>
<ref local=" department2DaoAuthenticationProvider"/>
</constructor-arg>
<property name="domainRegex">
<value>department2\\\w+</value>
</property>
</bean>
<bean id="authenticationManager"
class="net.sf.acegisecurity.providers.ProviderManager">
<property name="providers">
<list>
<ref local="department1AuthenticationProvider" />
<ref local="department2AuthenticationProvider" />
</list>
</property>
</bean>
Code:
/**
* An <code>AuthenticationProvider</code> decorator used to support multiple
* administrative domains.
*
* This decorator only works with <code>AuthenticationProvider</code>s that
* support <code>UsernamePasswordAuthenticationToken</code> using either a
* <code>String</code> or <code>User</code> as the Principal.
*
* A JDK regular expression is used to determine if a username provided in the
* Principal is in an administrative domain. If the username is
* <code>null</code> or does not match the regular expression,
* <code>authenticate()</code> returns null indicating this
* <code>AuthenticationProvider</code> does not support authentication for
* this domain. If the username matched the regular expression it may be
* modified before being delegated to the underlying
* <code>AuthenticationProvider</code>. See
* <code>setUsernameRegex()</code> for further information. The
* original username is replaced before the <code>Authentication</code> is
* returned.
*
* For example, <code>user1@department1.company.com</code> can be mapped to
* <code>user1</code> then authenticated against depatment1’s user store.
* Another AuthenticationProvider can be decorated to only authenticate
* usernames in the form <code>department2\\user</code> against department2’s
* user store.
*
*/
public class RegexMatchingProvider implements AuthenticationProvider {
// impl removed
public RegexMatchingProvider(AuthenticationProvider authenticationProvider) {
// impl removed
}
public Authentication authenticate(Authentication authentication)
throws AuthenticationException {
// impl removed
}
/**
*
* The expression used to determine if this AuthenticationProvider should be
* used for authentication.
*
* @param domainRegex
* The JDK regular expression to use to determine if this
* AuthenticationProvider should be used for authentication.
*/
public void setDomainRegex(String domainRegex) {
// impl removed
}
/**
*
* The expression provided here is used in the matching part of the
* substitution operation. Think Perl 5:
* s/$usernameRegex/$usernameReplacement/g
*
* See replaceAll() in java.util.regex.Matcher for further information.
*
* @param usernameRegex
* The JDK regular expression used to extract the domain specific
* username from the username provided.
*
*/
public void setUsernameRegex(String usernameRegex) {
// impl removed
}
/**
*
* The expression provided here is used as the substitution string in the
* substitution operation. Think Perl 5:
* s/$usernameRegex/$usernameReplacement/g
*
* See replaceAll() in java.util.regex.Matcher for further information.
*
* @param usernameReplacement
* The username will be replaced according to the expression
* provided. Dollar signs may be treated as references to
* captured subsequences.
*
*/
public void setUsernameReplacement(String usernameReplacement) {
// impl removed
}
}