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
ListableBeanFactoryinstance - Initialize the
net.sf.acegisecurity.Authenticationinterface with a proper reference implementation - Obtain an instance of the from the
ListableBeanFactoryconfiguration - Invoke the
AuthenticationProvider.authenticate()
- Get the instance of the
net.sf.acegisecurity.providers.dao.Userfrom theAuthenticationProvider.authenticate().getPrincipal()
- Check ALL of the following from the
Userobject:isEnabled(),isAccountNonLocked(),isAccountNonExpired(),isCredentialsNonExpired()
- Register the
Authenticationobject to theSecureContext - Register the
SecureContextobject 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