Just a note - you should not use the ThreadState stuff as shown in
your code sample.  Instead use my example that executes a Runnable and
calls the 'doBootstrap' method (that you implement).

As documented in the Subject wiki page, if you use ThreadState
objects, you _must_ ensure that a thread is cleaned up after use.
Just calling ThreadState.bind() is not good enough - you must also
clear() it at the end of the thread execution.

The Subject.execute* methods perform this cleanup automatically and
you don't need to worry about ThreadState objects - a cleaner
approach, and easier to use.  For your case, you should the
Subject.execute methods instead.  Manual ThreadState manipulation is
really best left to lower-level framework programming.

Best,

Les

On Thu, Oct 29, 2009 at 12:33 PM, Scott Ryan <[email protected]> wrote:
> SUCCESS!!!
>
> I had to attach to the current thread due to all the grailsy stuff going on
> in the bootstrap but here is my code that appears to work.  I will clean it
> up quite a lot and publish a solution on the mailing list and on my blog.
>
> import org.apache.shiro.subject.Subject
> import org.apache.shiro.subject.PrincipalCollection
> import org.apache.shiro.subject.SimplePrincipalCollection
> import org.apache.shiro.util.ThreadState
> import org.apache.shiro.subject.support.SubjectThreadState
> import org.apache.shiro.mgt.DefaultSecurityManager
> import org.apache.shiro.mgt.SecurityManager
>
> class BootStrap
> {
>
>    def shiroSecurityManager
>    def init =
>    {servletContext ->
>
> buildSubject()
> // RUN ALL your bootstrap code here
>
> void buildSubject()
>    {
> // TODO Clean this up and add all realms if requirred
>        Object userIdentity = "admin";
>        def realms = shiroSecurityManager.realms
>        println "ralsm cont" + realms?.size()
>        def realm
>        realms.each()
>        {
>            realm = it
>        }
>        //  Realm localizedRealm = shiroSecurityManager.realms
>        SecurityManager bootstrapSecurityManager = new
> DefaultSecurityManager(realm);
>        PrincipalCollection principals = new
> SimplePrincipalCollection(userIdentity, realm.getName());
>        Subject subject = new
> Subject.Builder(bootstrapSecurityManager).principals(principals).buildSubject();
>        ThreadState threadState = new SubjectThreadState(subject);
>        threadState.bind();
>    }
> }
>
> All of my domain objects extend the BaseDomain
>
> public abstract class BaseDomain
> {
>    static constraints =
>    {
>        // TODO Set some to be required
>        dateCreated(nullable: true)
>        createUser(nullable: true)
>        lastUpdated(nullable: true)
>        updateUser(nullable: true)
>    }
>    /** The date this entry was created */
>    Date dateCreated
>    /** The username that created this entry */
>    String createUser
>    /** The date this entry was last updated */
>    Date lastUpdated
>    /** The username that last updated this entry */
>    String updateUser
>    /** Before insert the database should populate the username
>     * on the createUser.  The timestamp will be taken care of by the
>     * grails framework automatically.
>     */
>    transient beforeInsert =
>    {
>        try
>        {
>            createUser =  SecurityUtils?.getSubject()?.getPrincipal()
>        }
>        catch (Exception ex)
>        {
>
>             log.fatal ("Exception in before Insert ", ex)
>
>        }
>    }
>    /** Before update the database should populate the username
>     * on the updateUser.  The timestamp will be taken care of by the
>     * framework automatically.
>     */
>    transient beforeUpdate =
>    {
>        try
>        {
>            updateUser = SecurityUtils?.getSubject()?.getPrincipal()
>        }
>        catch (Exception ex)
>        {
>
>            log.fatal ("Exception in before Update ", ex)
>
>        }
>    }
> }
>
>
> Thanks so much for all your assistance as I know a lot of people have been
> trying to get this to work.
>
>
> Scott Ryan
> President/CTO
> Soaring Eagle L.L.C.
> [email protected]
> (303) 263-3044
>
> On Oct 29, 2009, at 9:35 AM, Peter Ledbrook wrote:
>
>>> Yes I think it is not running in a request/response mode.  Just a dumb
>>> question as i implement your solution.  I tried this earlier but since
>>> Runnable is an interface it does not let me create one so I must be
>>> missing
>>> a parenthesis or something?
>>
>> Correct, BootStrap is executed during servlet context startup, so
>> there is not request or response.
>>
>>> I will try out your suggestions and offer feedback.  I think it would be
>>> nice to have access to both security managers from the plugin so you
>>> could
>>> use the same code during both processes.
>>
>> The BootStrap instances are auto-wired by Spring, so you have access
>> to the Spring application context. I would consider grabbing the
>> "shiroSecurityManager" bean and copying the realms from there into
>> your own temporary (non-web) security manager. I say copy the realms,
>> but I mean the references to them.
>>
>> That's if you even need the realms.
>>
>> Cheers,
>>
>> Peter
>
>

Reply via email to