在 bootstrap 中使用 groovy metaClass 模拟 Shiro SecurityUtils

发布于 2024-08-11 05:20:29 字数 2023 浏览 9 评论 0原文

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

我试图在 BootStrap.groovy 中模拟 Shiro SecurityUtils.getSubject() 方法。我决定采用这种方法是因为最新 Shiro 版本中的主题构建器在当前版本的 Nimble 插件(我正在使用)中不可用。我决定尝试使用 SecurityUtils.metaClass,但我有一种感觉,我错过了一些关于元类如何工作的非常基本的东西。作为参考,这里是我的 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 打印出主题,我会得到“罐头主题”。如果我尝试创建并保存 Trackable 子类的实例,我会得到:

此方法无法访问 SecurityManager,无论是绑定到
org.apache.shiro.util.ThreadContext 或作为 vm static
单例。请参阅 org.apache.shiro.SecurityUtils.getSubject()
方法 JavaDoc 对预期环境的解释
配置。

我是否遗漏了元类如何工作的一些重要内容?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

自在安然 2024-08-18 05:20:29

我知道发生了什么事。在我的 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 闭包的末尾。我做了一些谷歌搜索来仔细检查如何刷新我的休眠会话。然后我做了以下更改:

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 块。 :-)

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. :-)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文