问题描述
我正在使用具有域级安全性 (ACL) 的 Spring Security。
我有两个域 Company 和 Book。
class Company {
String name
hasMany = [books: Book]
}
class Book {
String title
belongsTo = [company: Company]
}
我读到 ACL 可以有一个 ,它可以从中继承其权限。
在服务中,我会使用这样的方法来设置新书卡的权限:
@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
}
只要用户拥有这本书的权限,这就能正常工作。 但是,我想将父对象(公司)的权限继承给本书。 当用户有权访问公司时,我希望它也有权访问公司的所有书籍。
我在看到有一个方法setParent()
。
如果您这样做,这将起作用:
AclImpl acl = aclUtilService.readAcl(book)
acl.setParent(aclUtilService.readAcl(book.company))
aclService.updateAcl(acl)
使用上面的代码将在数据库中设置 book 的父级。
如何在 Spring Security ACL 中使用继承?
1楼
您可以这样做而不是使用父 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)")
如果当前用户已读取父级的 ACL,则返回 true