Faking a Valid Acegi SecurityContext in a UnitTest
When using acegi security in your code, you will often have a setup, where the authentication information is put on a ThreadLocal somewhere inside SecurityContextHolder and then used later on in the application code. Actually, acegi operates with strategies for how to store the security information, but more often than not, it is on a ThreadLocal storage.
In my current project, we have an acegi filter defined in web.xml, which takes care of basic authentication. After authentication, the auth information can be retrived from the SecurityContext, as long as we are executing in the same thread. It can also be helpful in spring based cronjobs, where a trigger thread periodically executes a method on a spring bean. These execute in no particular authentication context, as they have been through no filter, like the one mentioned above. If you now which username and password the job is to execute as, you can fake it with a call like the one in setUp show below.
Here is how one can do do it:
Fake It Directly into the Holder
import org.acegisecurity.context.SecurityContextHolder;
import org.acegisecurity.providers.UsernamePasswordAuthenticationToken;
import org.acegisecurity.userdetails.User;
import org.acegisecurity.GrantedAuthority;
...
@Override
protected void setUp() throws Exception {
super.setUp();
SecurityContextHolder.getContext().setAuthentication(
new UsernamePasswordAuthenticationToken(
new User("testuser", "aBigSecret", true, true, true, true, new GrantedAuthority[0]),
"aBigSecret"
)
);
}
@Override
protected void tearDown() throws Exception {
SecurityContextHolder.clearContext();
super.tearDown();
}
The two parameters given to the UsernamePasswordAuthenticationToken instance I had to dig out what to put into. The javadocs says this about them:
* @param principal DOCUMENT ME!
* @param credentials DOCUMENT ME!
…
and as they both are of type java.lang.Object, I had to do guess-work and digging in the sources. I guess they are Object typed because what you put into them depends on how you authenticate!? The example above work with acegi basic authentication filter, which is a simple username/password authentication mechanism. I expect what to put into these can vary, if you use client-certificates or some other authentication mechanism.
Another Way
It turns out there is another way to do it.
In the package org.acegisecurity.providers where UsernamePasswordAuthenticationToken lives, there are two interesting classes: TestingAuthenticationProvider and TestingAuthenticationToken. I have not tried these myself, and the documentation on the acegi website does not mention them (except in the apidocs, of course). I googled a bit on them, and could not find much. I found one entry though, from Gavin Terrill, who write about Junit testing with Acegi Security.

