English 中文(简体)
Using groovy metaClass to mock out Shiro SecurityUtils in bootstrap
原标题:

For further background, see http://grails.markmail.org/message/62w2xpbgneapmhpd

I m trying to mock out the Shiro SecurityUtils.getSubject() method in my BootStrap.groovy. I decided on this approach because the Subject builder in the latest Shiro version isn t available in the current version of the Nimble plugin (which I m using). I decided to try playing with the SecurityUtils.metaClass but I have a feeling I m missing something very fundamental about how metaClasses work. For reference, here s my Trackable class:

    abstract class Trackable {
       User createdBy
       Date dateCreated
       User lastUpdatedBy
       Date lastUpdated

       static constraints = {
           lastUpdated(nullable:true)
           lastUpdatedBy(nullable:true)
           createdBy(nullable:true)
       }

       def beforeInsert = {
           def subject

           try {
               subject = SecurityUtils.subject
           } catch (Exception e) {
               log.error "Error obtaining the subject.  Message is [${e.message}]"
           }

           createdBy = (subject ? User.get( subject.principal ) :
User.findByUsername("admin"))
       }

       def beforeUpdate = {
           def subject

           try {
               subject = SecurityUtils.subject
           } catch (Exception e) {
               log.error "Error obtaining the subject.  Message is [${e.message}]"
           }

           lastUpdatedBy = (subject ? User.get( subject.principal ) :
User.findByUsername("admin"))
       }
   }

In my BootStrap.groovy, I have this:

   def suMetaClass = new ExpandoMetaClass(SecurityUtils)

   suMetaClass. static .getSubject = {[getPrincipal:{2}, toString:{"Canned Subject"}] as Subject}

   suMetaClass.initialize()

   SecurityUtils.metaClass = suMetaClass

And that works... sort of. If I print out the subject from BootStrap.groovy I get "Canned Subject". If I try to create and save instances of subclasses of Trackable, I get:

No SecurityManager accessible to this method, either bound to
the org.apache.shiro.util.ThreadContext or as a vm static
singleton.  See the org.apache.shiro.SecurityUtils.getSubject()
method JavaDoc for an explanation of expected environment
configuration.

Am I missing something integral about how metaClasses work?

最佳回答

I figured out what was happening. In my BootStrap I was doing something like this:

def init = { servletContext->
  switch (Environment.current.name) {
    case "local":
      def suMetaClass = new ExpandoMetaClass(SecurityUtils)
      suMetaClass. static .getSubject = {[getPrincipal:{2}, toString:{"Canned Subject"}] as Subject}
      suMetaClass.initialize()
      SecurityUtils.metaClass = suMetaClass

      new TrackableSubClass().save()

      //Create some other domain instances

      SecurityUtils.metaClass = null
  }
  //Create a couple domain instances that aren t environment specific
}

I added some debug statements and saw that the errors I was seeing were happening at the end of the init closure. I did some googling to double check how to flush my Hibernate session. Then I made the following changes:

def sessionFactory

def init = { servletContext->
  switch (Environment.current.name) {
    case "local":
      def suMetaClass = new ExpandoMetaClass(SecurityUtils)
      suMetaClass. static .getSubject = {[getPrincipal:{2}, toString:{"Canned Subject"}] as Subject}
      suMetaClass.initialize()
      SecurityUtils.metaClass = suMetaClass

      new TrackableSubClass().save()

      //Create some other domain instances

      sessionFactory.currentSession.flush()

      SecurityUtils.metaClass = null
  }
  //Create a couple domain instances that aren t environment specific
}

That seems to have completely resolved the issue and now I should be able to remove the cumbersome try/catch blocks from Trackable. :-)

问题回答

暂无回答




相关问题
Groovy - how to exit each loop?

I m new to Grails/Groovy and am trying to find a node in a an xml file; I ve figured out how to iterate over all of them, but I want to exit the loop when the target node is found. I ve read that ...

Eclipse Spring Builder set properties with Groovy beans

I typically use groovy to construct simple bean but the Spring IDE plugin to eclipse fails to build when I try to set a property that is generated by groovy without an explicit setter. For example, ...

How can I get this snippet to work?

I d like to port a little piece of code from Ruby to Groovy, and I m stuck at this: def given(array,closure) { closure.delegate = array closure() } given([1,2,3,4]) { findAll { it > 4} ...

Changing the value in a map in Groovy

This is about a very basic program I m writing in Groovy. I have defined a map inside a method: def addItem() { print("Enter the item name: ") def itemName = reader.readLine() print(...

Is functional Clojure or imperative Groovy more readable?

OK, no cheating now. No, really, take a minute or two and try this out. What does "positions" do? Edit: simplified according to cgrand s suggestion. (defn redux [[current next] flag] [(if flag ...

热门标签