使用groovy metaClass在bootstrap中模拟Shiro SecurityUtils

时间:2009-11-10 13:06:12

标签: grails groovy metaprogramming shiro bootstrapping

有关更多背景信息,请参阅http://grails.markmail.org/message/62w2xpbgneapmhpd

我正试图在我的BootStrap.groovy中模拟Shiro SecurityUtils.getSubject()方法。我决定使用这种方法,因为最新的Shiro版本中的Subject构建器在当前版本的Nimble插件(我正在使用)中不可用。我决定尝试使用SecurityUtils.metaClass,但我有一种感觉,我错过了关于metaClasses如何工作的非常基本的东西。作为参考,这是我的Trackable类:

    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"))
       }
   }

在我的BootStrap.groovy中,我有这个:

   def suMetaClass = new ExpandoMetaClass(SecurityUtils)

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

   suMetaClass.initialize()

   SecurityUtils.metaClass = suMetaClass

这有用......有点儿。如果我从BootStrap.groovy打印出主题,我会得到“Canned Subject”。如果我尝试创建并保存Trackable子类的实例,我得到:

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.

我是否遗漏了关于metaClasses如何工作的不可或缺的部分?

1 个答案:

答案 0 :(得分:1)

我弄清楚发生了什么。在我的BootStrap中,我做了类似的事情:

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
}

我添加了一些调试语句,发现我看到的错误发生在init闭包的末尾。我做了一些谷歌搜索,以仔细检查如何刷新我的Hibernate会话。然后我做了以下更改:

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
}

这似乎完全解决了这个问题,现在我应该能够从Trackable中删除繁琐的try / catch块。 : - )