【问题标题】:Spring Security ACL Inheriting: How does it really works?Spring Security ACL 继承:它是如何工作的?
【发布时间】:2015-10-16 09:54:25
【问题描述】:

我正在使用 Spring Security 和域级安全 (ACL)。

我有两个域 Company 和 Book。

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 的父级。

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

【问题讨论】:

    标签: java spring grails groovy spring-security


    【解决方案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 继承,请确保子 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

    【讨论】:

    • entriesInheriting 始终设置为 true。问题是如何继承权限。如何测试继承的权限?
    • 如何在@PreAuthorize 中检查继承的权限?
    • 你会如何查找父母?如果 parent 是 class A extends B {} 并且对象标识是为超类 B 编写的。您不想为类 A 创建新的对象标识怎么办?您将如何处理?
    • 谢谢。您可能对这个问题有所了解:stackoverflow.com/questions/31597897/…
    猜你喜欢
    • 1970-01-01
    • 2013-02-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-17
    • 2019-07-18
    • 2014-02-15
    相关资源
    最近更新 更多