In a Spring Security 3.2 based application I need to authenticate users against two different providers, based on a certain pattern in their username AND their remote ip address.
In case they match certain rules, they should be authenticated against an ActiveDirectoryLdapAuthenticationProvider
, otherwise with a standard AuthenticationProvider
using an already exisiting custom implementation of UserDetailsService
.
What do I need to extend ? AuthenticationManager
or AuthenticationProvider
? Any example code would be highly appreciated :-)
Note: I have already successfully tried adding two <authentication-provider />
nodes in <authentication-manager />
, and this worked fine. But it bothers me that my Ldap-server is hit for every authentication attempt (even the ones which are not meant for it)
You could create a wrapper which does the check for the pattern/ip-address if it matches calls the delegate else return null.
public class FilteringAuthenticationProvider implements AuthenticationProvider {
private final AuthenticationProvider delegate;
public FilteringAuthenticationProvider(AuthenticationProvider delegate) { this.delegate=delegate;}
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
Object details = authentication.getDetails();
String username = authentication.getPrincipal().toString();
String remoteAddress = null;
if (details instanceof WebAuthenticationDetails) {
remoteAddress = ((WebAuthenticationDetails) details).getRemoteAddress();
}
if (matches(remoteAddress, username)) {
return delegate.authenticate(authentication);
}
return null
}
private boolean matches(String remoteAddress, String Username) {
// your checking logic here
}
}
Something like this. Then configure it in your security configuration and let it wrap the ActiveDirectoryLdapAuthenticationProvider
.
<sec:authentication-manager>
<sec:authentication-provider ref="filteringLdapProvider" />
<sec:authentication-provider>
<user-service ref="customUserDetailsService" />
</sec:authentication-provider>
</sec:authentication-manager>
<bean id="filteringLdapProvider" class="FilteringAuthenticationProvider">
<constructor-arg ref="ldapProvider" />
</bean>
<bean id="ldapProvider" class="ActiveDirectoryLdapAuthenticationProvider">
...
</bean>
Something like this.