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 > >
