使用Grails安全ACL过滤选择下拉列表

时间:2012-03-16 01:06:13

标签: spring security grails acl

我正在使用spring-security-acl插件实现ACL安全性。我有以下域类:

package test
class Subitem {

   String name

   static belongsTo = [employer: Employer]

   static constraints = {
    name blank: false
   }
}

package test
class Employer {
   String name

   static hasMany = [users: User, items: Subitem]
   static belongsTo = User

   static constraints = {
    name blank: false, unique: true
   }

   String toString() {
    name
   }
}

在用于创建Subitem的create.gsp文件中,有以下语句:

<g:select id="employer" name="employer.id" from="${test.Employer.list()}" optionKey="id" required="" value="${subitemInstance?.employer?.id}" class="many-to-one"/>

来自EmployerController:

    def list = {
    params.max = Math.min(params.max ? params.int('max') : 10, 100)
    [employerInstanceList: employerService.list(params),
     employerInstanceTotal: employerService.count()]
 }

按照here给出的教程,我将处理Employer的一些功能移到了一个名为EmployerService的服务中:

@PreAuthorize("hasRole('ROLE_USER')")
@PostFilter("hasPermission(filterObject, read)")
List<Employer> list(Map params) {
   Employer.list params
}
int count() {
   Employer.count()
}

使用ACL限制对任何给定Employer类实例中的信息的访问。目前,我可以在下拉列表中看到数据库中所有Employer实例,我认为这是因为我使用的是控制器列表(),而不是服务列表() - 但是,我只想查看已过滤的列表雇主领域类。但是,如果我替换g:select with:

<g:select id="employer" name="employer.id" from="${test.EmployerService.list()}" optionKey="id" required="" value="${subitemInstance?.employer?.id}" class="many-to-one"/>

然后我收到内部服务器错误,因为我没有将Map参数传递给service list()函数(我不知道如何在标记内执行此操作):

URI /security/subitem/create
Class groovy.lang.MissingMethodException
Message No signature of method: static test.EmployerService.list() is applicable for argument types: () values: [] Possible solutions: list(java.util.Map), is(java.lang.Object), wait(), find(), wait(long), get(long)

我只想查看来自EmployerService list()函数的信息 - 我该怎么做?如何从间隙中引用正确的函数?

  • 编辑08年3月16日:感谢@OverZealous,这真的很有帮助,我没有意识到这一点。但是,我已经尝试过,仍然会遇到同样的问题。我在Employer和EmployerService list()函数中都放了一个println()语句,并且可以看到在解析g:select标记时实际上似乎都没有被调用(即使我离开g:select来引用雇主)。是否有另一个版本的list()函数被调用?或者如何获得g:select以考虑ACL?

2 个答案:

答案 0 :(得分:0)

只需将服务中的方法签名更改为:

List<Employer> list(Map params = [:]) {
   Employer.list params
}

此更改正在添加:= [:]。这为params提供了默认值,在本例中为空映射。

(这是一个Groovy功能,BTW。您可以在任何方法或闭包中使用它,其中参数是可选的,并且您想提供默认值。)

答案 1 :(得分:0)

好的,我把它解决了,这是解决同样问题的其他任何人的解决方案。

通过Subitem的create.gsp文件和SubitemController渲染create Subitem页面。诀窍是修改SubitemController create()闭包:

class SubitemController {

def employerService

def create() {
    // this line was the default supplied method:
    // [subitemInstance: new Subitem(params)]
    // so replace with the following:
    params.max = Math.min(params.max ? params.int('max') : 10, 100)
    [subitemInstance: new Subitem(params), employerInstanceList: employerService.list(params),
     employerInstanceTotal: employerService.count()]
    }
}

所以现在当g:要求SubitemController在子项视图中选择雇主列表时,它会调用EmployerService,它提供正确的答案。我们简单地添加了两个返回到视图的其他变量,这些变量可以在视图中的任何位置引用(例如通过g:select标记)。

对我来说,教训是视图与Controller进行交互,控制器可以引用服务:看起来,服务不能很好地与视图一起使用。