当前位置: 代码迷 >> java >> Spring Security ACL 继承:它究竟是如何工作的?
  详细解决方案

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

热度:48   发布时间:2023-07-17 20:14:36.0

我正在使用具有域级安全性 (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 中使用继承?

您可以这样做而不是使用父 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 继承,请确保子项的AclObjectIdentityentriesInheriting设置为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

  相关解决方案