Spring Security ACL继承:它是如何工作的?

时间:2015-07-26 00:13:57

标签: java spring grails groovy spring-security

我正在使用具有域级安全性(ACL)的Spring Security。

我有两个域名公司和书。

class Company {
 String name
 hasMany = [books: Book]
}

class Book {
 String title
 belongsTo = [company: Company]
}

我读过一个ACL可以有一个Parent,它从。

继承了它的权限

在服务中我会有这样的方法来设置新的图书卡的权限:

@PreAuthorize("hasRole('ROLE_ADMIN') or hasPermission(#book, admin)")
void addPermission(Book book, String username, Permission permission) {
  aclUtilService.addPermission(book, username, permission)
} 

这样可以正常工作并为新书实例创建权限。我还有一个更新方法,可以在更新本书之前检查权限。

@PreAuthorize("hasPermission(#book, write) or hasPermission(#book, admin)")
Book update(Book book, Map params = [:]) {    
  book.properties = params
  book.save(flush:true) 
  return book
}

只要用户拥有该书的权限,这就可以正常工作。但是,我希望将父对象(公司)的权限用户继承到该书。当用户获得我想要的公司许可时,它也允许所有公司的书籍。

我在AclImp中看到有一个方法setParent()。这样做有用:

AclImpl acl = aclUtilService.readAcl(book)
acl.setParent(aclUtilService.readAcl(book.company))
aclService.updateAcl(acl)

使用上面的代码将在数据库中设置book的parent。

如何在Spring Security ACL中使用继承?

1 个答案:

答案 0 :(得分:2)

您可以这样做,而不是使用父ACL:

@PreAuthorize("hasPermission(#book.company, write) or hasPermission(#book.company, admin)")
Book update(Book book, Map params = [:]) {    
  book.properties = params
  book.save(flush:true) 
  return book
}

如果您希望从父ACL继承,请确保将子AclObjectIdentity entriesInheriting设置为true,例如使用createAcl方法下面:

void createAcl(Class clazz, Long id, String sid, AclObjectIdentity parent) {
    clazz = ProxyUtils.unproxy(clazz)
    AclClass aclClass = AclClass.findOrSaveByClassName(clazz.name)
    AclSid ownerSid = AclSid.findOrSaveBySidAndPrincipal(sid, true)
    AclObjectIdentity oid = findOrCreateObjectIdentity(aclClass, ownerSid, id, parent, true)
}

AclObjectIdentity findOrCreateObjectIdentity(AclClass aclClass, AclSid ownerSid, Long id, AclObjectIdentity parent, boolean entriesInheriting) {
    assert aclClass, "aclClass is required"
    assert null != id, "id is required"

    AclObjectIdentity oid = AclObjectIdentity.findOrCreateByAclClassAndObjectId(aclClass, id)
    if (null == oid.id) {
        oid.entriesInheriting = entriesInheriting
        oid.owner = ownerSid
        oid.parent = parent
        oid.save(flush: true, failOnError: true)
    }
    oid
}

如果ACL继承@PreAuthorize("hasPermission(#child, read)")将返回true,如果当前用户已读取父ACL的