Yup, this answers quite a few of my questions. Any chance this could be put 
somewhere as a part of the official documentation as well?

Thanks heaps, tests are now running perfectly :-)

/Janne

On Nov 9, 2010, at 21:02 , Les Hazlewood wrote:

> Shiro can be configured dynamically in a single JVM - I do it all the time on 
> a product I'm working on. I guess it means what you mean by 'configure 
> dynamically'.  I'm not swapping out the security manager entirely however.  I 
> re-configure the same instance (maybe swap out its AuthorizationStrategy, 
> etc).
> 
> When a Subject instance is created (a DelegatingSubject specifically), it 
> accepts a SecurityManager instance at that time. It holds on to that instance 
> throughout it's lifetime.  In other words, you can call 
> SecurityUtils.setSecurityManager at any time after that point (which sets a 
> VM-static singleton) and the previously instantiated Subject instance(s) will 
> not 'see' the new static SecurityManager instance.
> 
> Subject object instances themselves are intended to have a very short VM 
> lifetime - typically instantiated at the beginning of a thread's execution 
> and removed/garbage collected at the end of its execution.  Swapping out a 
> SecurityManager entirely during a thread's execution is not something that 
> people have requested in the past, so we haven't built it.  I'm not sure how 
> often this would occur in practice for running applications to be honest.
> 
> So to sidestep this for unit testing scenarios, there are two good approaches 
> that I can think of:
> 
> 1)  Use a Subject.Builder and pass in the SecurityManager instance you want 
> it to use during the test.  The constructed instance is used to 'execute' a 
> method under test:
> 
> Subject subject = new Subject.Builder(mySecurityManager).buildSubject();
> subject.execute( new Runnable() {
>     executeMethodUnderTest();
> });
> 
> When 'executeMethodUnderTest' executes, the subject.execute method will 
> guarantee thread set-up and clean-up before and after the method's execution, 
> respectively.  Also, any call to SecurityUtils.getSubject() within that 
> method (or any methods it calls) will work correctly.
> 
> 2) Set up and tear down the Shiro thread state before and after a test 
> methods's execution.  This is the exact same thing as #1, but requires you to 
> do a little more work.  See the http://shiro.apache.org/subject.html page, 
> "Manual Association" section for more detail.  You would do this in @Before 
> and @After methods in JUnit:
> 
> private ThreadState shiroThreadState;
> 
> @Before
> public void setUpSubject() {
>     Subject testSubject = Subject.Builder(securityManagerForTheTest). ... 
> .buildSubject();
>     shiroThreadState = new SubjectThreadState(testSubject);
>     shiroThreadState.bind();
> }
> 
> @After
> public void tearDownSubject() {
>     shiroThreadState.restore();  //or clear(); either is fine.
> }
> 
> #1 is easier, but it might make your test cases look a little ugly.  #2 is a 
> little more time consuming, but more flexible and arguably nicer when keeping 
> your tests clean.  You can have this in a test superclass and your subclasses 
> wouldn't ever have to worry about it.  They could call 
> SecurityUtils.getSubject() at any time and it would all work out.
> 
> Note that the Subject.Builder constructor doesn't require a securityManager 
> instance - if you don't provide one, it will call 
> SecurityUtils.getSecurityManager() and use that one instead.  I typically 
> like to specify the instance myself because I personally don't like using 
> static singletons if I can avoid them, and at least in testing, I find it to 
> be a bit more deterministic.
> 
> Anyway, I hope this helps.  Does this all make sense?
> 
> Best,
> 
> -- 
> Les Hazlewood
> Founder, Katasoft, Inc.
> Application Security Products & Professional Apache Shiro Support and 
> Training:
> http://www.katasoft.com
> 
> On Tue, Nov 9, 2010 at 12:47 AM, Janne Jalkanen <[email protected]> 
> wrote:
> 
> And to respond to myself - the problem turns out to be that I had one 
> instance where Shiro was configured implicitly and not using the SHIRO_CONFIG 
> below. Turns out that this causes a conflict if you configure Shiro twice 
> with different settings within the same JVM.
> 
> It would be good if there was some sort of a check for this - the exception 
> message is not exactly helping here.
> 
> /Janne
> 
> On 8 Nov 2010, at 22:20, Janne Jalkanen wrote:
> 
>> Folks,
>> 
>> I'm rather stymied at the following problem: Whenever I run my unit tests 
>> one at a time, everything works. But when I run the entire suite, the tests 
>> fail due to 
>> 
>>         SecurityUtils.getSubject().logout(); // Ensure we are logged out
>>         SecurityUtils.getSubject().login( new 
>> UsernamePasswordToken("[email protected]","foobar") );
>>  
>> The failure is 
>> 
>> org.apache.shiro.authc.IncorrectCredentialsException: The credentials 
>> provided for account [org.apache.shiro.authc.UsernamePasswordToken - 
>> [email protected], rememberMe=false] did not match the expected credentials.
>>      at 
>> org.apache.shiro.realm.AuthenticatingRealm.getAuthenticationInfo(AuthenticatingRealm.java:191)
>>      at 
>> org.apache.shiro.authc.pam.ModularRealmAuthenticator.doSingleRealmAuthentication(ModularRealmAuthenticator.java:179)
>>      at 
>> org.apache.shiro.authc.pam.ModularRealmAuthenticator.doAuthenticate(ModularRealmAuthenticator.java:264)
>>      at 
>> org.apache.shiro.authc.AbstractAuthenticator.authenticate(AbstractAuthenticator.java:198)
>>      at 
>> org.apache.shiro.mgt.AuthenticatingSecurityManager.authenticate(AuthenticatingSecurityManager.java:106)
>>      at 
>> org.apache.shiro.mgt.DefaultSecurityManager.login(DefaultSecurityManager.java:269)
>>      at 
>> org.apache.shiro.subject.support.DelegatingSubject.login(DelegatingSubject.java:247)
>>      at 
>> com.thinglink.site.stripes.AccountActionBeanTest.setup(AccountActionBeanTest.java:43)
>> <rest is snipped away>
>> 
>> I've tried different kinds of Shiro configurations, and the one that seems 
>> to work best right now looks like
>> 
>>     /** Configuration that we use in tests. */
>>     private static final String SHIRO_CONFIG = 
>>         "[main]\n"+
>>         "credentialsMatcher = 
>> org.apache.shiro.authc.credential.Sha256CredentialsMatcher\n"+
>>         "credentialsMatcher.storedCredentialsHexEncoded = false\n"+
>>         "credentialsMatcher.hashSalted = true\n"+
>>         "cacheManager = 
>> org.apache.shiro.cache.MemoryConstrainedCacheManager\n"+
>>         "myRealm = com.thinglink.site.shiro.CassandraRealm\n"+
>>         "myRealm.credentialsMatcher = $credentialsMatcher\n"+
>>         "myRealm.cacheManager = $cacheManager\n"+
>>         "securityManager = org.apache.shiro.mgt.DefaultSecurityManager\n"+
>>         "securityManager.realm = $myRealm\n";
>> 
>> // For shiro we use our internal configuration, not the one that's found 
>> from classpath
>>         Ini ini = new Ini();
>>         ini.load( SHIRO_CONFIG );
>>         IniSecurityManagerFactory smf = new IniSecurityManagerFactory( ini );
>>         SecurityUtils.setSecurityManager( smf.getInstance() );
>> 
>> I've tried using a WebIniSecurityManagerFactory, but the test framework I'm 
>> using does not fully implement the Servlet spec, so it's not that useful; it 
>> fails in interesting ways and getting cookies is a pain.  So I figured I 
>> should try just simply the basic DefaultSecurityManager as everything runs 
>> in a single thread anyway.
>> 
>> This is with 1.1.0 release.
>> 
>> Any ideas as to what could explain why the tests aren't running if I run all 
>> the tests? The fun thing is that this is the *only* test currently which 
>> actively tries to log in.
>> 
>> /Janne

Reply via email to