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