【问题标题】:Property interception of Grails domain classesGrails域类的属性拦截
【发布时间】:2010-02-11 17:43:38
【问题描述】:

我想拦截对域类属性的调用以实现访问控制。

我的第一次尝试是覆盖 setProperty 和 getProperty。通过这样做,我禁用了 Grails 域类的所有不错的功能,例如

domainClass.properties = params

以及数据类型的自动转换。

下一个尝试是使用 DelegatingMetaClass,它至少使我能够在实际调用周围打印出一些不错的日志消息。但我不知道如何访问实际对象来评估权限。

最后,groovy.lang.Interceptor 似乎是一个不错的选择,因为我可以访问实际的对象。但这是正确的方法吗?如何强制拦截所有域类?

非常感谢。

问候,丹尼尔

【问题讨论】:

    标签: grails class dns intercept


    【解决方案1】:

    只要您引用真实版本,您就可以覆盖 getProperty 和 setProperty。在 BootStrap 中添加这样的代码,为所有域类添加拦截器:

    class BootStrap {
    
       def grailsApplication
    
       def init = { servletContext ->
    
          for (dc in grailsApplication.domainClasses) {
             dc.class.metaClass.getProperty = { String name ->
                // do stuff before access
                def result
                def metaProperty = delegate.class.metaClass.getMetaProperty(name)
                if (metaProperty) {
                   result = metaProperty.getProperty(delegate)
                }
                else {
                   throw new MissingPropertyException(name, delegate.class)
                }
                // do stuff after access
                result
             }
    
             dc.class.metaClass.setProperty = { String name, value ->
                // do stuff before update
                def metaProperty = delegate.class.metaClass.getMetaProperty(name)
                if (metaProperty) {
                   metaProperty.setProperty(delegate, value)
                }
                else {
                   throw new MissingPropertyException(name, delegate.class)
                }
                // do stuff after update
             }
          }
       }
    
       def destroy = {}
    }
    

    【讨论】:

    • 您好,非常感谢您的快速回复。您的代码确实对我有很大帮助。不幸的是,我看不到如何在我的域类对象上调用方法。例如,我有一个名为 A 的域类,它提供了一个名为 isReadable(String propertyName) 的方法。那么如何在 get 或 setProperty 方法中调用这个函数呢?我可以通过delegate.metaClass.getMetaMethod("isReadable", java.lang.String) 找到元方法,但是调用总是会导致异常(java.lang.IllegalArgumentException: object is not an instance of declaring class)。问候,丹尼尔
    • 一种方法是用调用某个助手类替换“访问前做点什么”注释,并在那里进行访问检查。类似“PropertyChecker.isReadable(delegate.class, name)”的东西,其中 PropertyChecker.isReadable(Class clazz, String name) 执行类似“if (clazz == Person && name == 'username') { ... }”的操作。该助手还可以访问登录用户以进行更细粒度的访问检查。这很快就会变得丑陋,因此您需要想出一些紧凑的方式来表示允许人们更改或阅读的内容以及何时。
    • 感谢您的回复。但我不明白,为什么我不能访问类中的方法。我想,通过定义 setProperty 方法,这个方法实际上被替换了,就好像它是写在域类本身中一样。您的 PropertyChecker 示例表明,我不能使用实际对象,而是使用类。不幸的是,这对我来说还不够,因为对象本身会根据其状态计算权限。还有其他可能如何拦截集合并获取属性调用吗?问候,丹尼尔
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-10-15
    • 2016-12-03
    • 1970-01-01
    • 2011-01-28
    • 1970-01-01
    • 1970-01-01
    • 2013-08-21
    相关资源
    最近更新 更多