Hi Janne,

I threw this together today:

http://shiro.apache.org/testing.html

Feedback is welcome.  I hope it helps!

Best,

Les

On Sun, Nov 21, 2010 at 8:03 AM, Janne Jalkanen
<[email protected]> wrote:
>
> 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