Testing Acegi Security's Provider-based Authentication
I am taking down this note as this process is very hard to remember when finalized and has been stabilized. The authentication process is very straightforward because most of the dirty works are handled by authentication providers. We will take the assumption that the reader is already familiar with Spring's application-context XML configurations in Acegi. We'll write a testable code based on JUnit. But first we have to enumerate the steps our authentication method will going to take:
In code, this is how it looks like:
Listing 1:
The test code should assert for the
Listing 1:
To do this test properly, all the AOP-based interceptors must be disabled since it will not be ran on a web container or application server. From a controller class (such as Webwork2 action classes) the
- Initialize a
ListableBeanFactory
instance - Initialize the
net.sf.acegisecurity.Authentication
interface with a proper reference implementation - Obtain an instance of the from the
ListableBeanFactory
configuration - Invoke the
AuthenticationProvider.authenticate()
- Get the instance of the
net.sf.acegisecurity.providers.dao.User
from theAuthenticationProvider.authenticate().getPrincipal()
- Check ALL of the following from the
User
object:isEnabled()
,isAccountNonLocked()
,isAccountNonExpired()
,isCredentialsNonExpired()
- Register the
Authentication
object to theSecureContext
- Register the
SecureContext
object toContextHolder.setContext()
static method.
In code, this is how it looks like:
Listing 1:
public boolean authenticate(String username, String password) {
Authentication authentication =
new UsernamePasswordAuthenticationToken(username, password);
SecureContext secureContext = new SecureContextImpl();
//have chose daoAuthenticationProvider for this.
AuthenticationProvider provider =
(AuthenticationProvider)beanFactory.getBean("daoAuthenticationProvider");
Authentication auth = provider.authenticate(authentication);
System.out.println(auth.getName());
User user = (User)auth.getPrincipal();
if (user.isAccountNonExpired() && user.isAccountNonLocked() &&
user.isCredentialsNonExpired() && user.isEnabled()){
auth.setAuthenticated(true);
}
secureContext.setAuthentication(auth);
ContextHolder.setContext(secureContext);
return auth.isAuthenticated();
}
The test code should assert for the
isAuthenticated()
method with something like this:Listing 1:
public void testAuthenticate() {
String[] contexts = {"applicationContext-acegi-security.xml",
"applicationContext-common-business.xml",
"applicationContext-common-authorization.xml"};
ListableBeanFactory beanFactory =
new ClassPathXmlApplicationContext(contexts);
UserAuthenticate authenticate = new UserAuthenticate(beanFactory);
//we assume that you are familiar with JUnit
assertTrue(authenticate.authenticate("scott", "wombat"));
}
To do this test properly, all the AOP-based interceptors must be disabled since it will not be ran on a web container or application server. From a controller class (such as Webwork2 action classes) the
authenticate()
method at Listing 2 will be shorter because the ContextHolder
already has the security credentials provided by AOP interceptors executed during initialization of UsernamePasswordAuthenticationToken
class. But for the sake of making a testable code, I have provided those checks for clarity.
Comments