复杂应用的高效ACL架构(关系型数据库、图形数据库?)

7

我正在使用Java / Spring构建一个相当复杂的Web应用程序,并且至少有两个不同的数据库:

  • 主数据的关系型数据库
  • MongoDB 用于文件(通过GridFS),以及其他数据CLOBs / JSON等。

下一步是授权。简单的基于角色的授权不足以满足需求,因为用户应该被允许/禁止查看/修改不同的资源。尽管我想到了 ACL。

最常见的简单ACL表格可能如下所示:

TABLE  | FIELDS
-------+--------------
class  | id, className
object | id, class_id, objectId
acl    | id, object_id, user_id, permissionBitMask (crud)

但是很遗憾,这对我的需求来说还不够:(
我还需要:
- 角色: - 每个用户可以有多个角色, - 一个访问控制列表条目也可以属于一个角色。 - 更多权限: - 例如:每个项目可以有多个任务,但是具有修改项目详情权限的用户不能创建此项目的新任务。因此必须有单独的权限进行控制。 - 不同类型的对象ID: - 关系型数据库表将使用UUID代理键(因此至少在此处无需处理复合键)。 - 但是MongoDB当然使用其自己的ObjectId。 - 另外,我将在代码中拥有一些静态资源,它们也必须受到访问限制。 - 父对象用于继承权限。
如果将所有这些方面结合起来,就可以得到以下表结构:
TABLE          | FIELDS
---------------+--------------
class          | id, className
object         | id, class_id, objectId, parent_object_id
acl            | id, object_id, user_id, role_id
permission     | id, permissionName
acl_permission | id, acl_id, permission_id, granted

当然,我可以将表拆分为两个表(1. 对象+用户,2. 对象+角色),但我认为这并不重要。

"objectId" 将是一个简单的VARCHAR类型,我的应用程序必须将其从/转换为字符串。否则,我会为不同的ObjectId类型拥有5个额外的表。这会导致5个额外的JOIN操作...

现在,基本的查找查询将类似于:

SELECT p.granted
  FROM acl a
  JOIN acl_permission p
    WHERE p.permission_id = ?
      AND (
           a.object_id = ? AND a.user_id = ?
        OR a.object_id = ? AND a.role_id IN (?)
      )

权限被缓存,当前用户的角色也通过会话上下文进行了缓存。granted仅指示用户是否具有该权限。

然后,我还需要应用递归SELECT,以便在当前对象没有ACL条目时获取父对象的ACL。

这不太高效。那么有什么替代方案吗?我的想法:

  • 不同的DB模式(任何想法!)
  • Neo4j等图形数据库。

Neo4j优势:

  • 查找具有权限条目的第一个父级对于此DB来说是一项简单的任务
  • 在ACL条目中存储权限数组是可能的->无需JOIN
  • 基本上,我可以将所有信息存储在单个节点中:

.

{
  class: ClassName,
  object: ObjectId,
  parent: RelationToParentNode,
  user: UserId,
  role: RoleId,
  grantedPermissions: [Permission1, Permission2, ...]
}

(除了在数组内列出的每个权限外,所有其他权限都自动未被授予。在Neo4j数组中无法存储复杂类型,因此无法存储诸如permissions:[{Permission1:true},{Permission2:false}]之类的内容。)
当然,也可以将Permissions和Classes作为单独的节点存储,并将它们全部链接在一起。但是我不知道在Neo4j中使用哪种方法更好。
这方面有什么想法吗?是否有现成的解决方案?也许使用MongoDB实现ACL有其原因?
我了解了XACML和OAuth(2),但似乎都需要额外的ACL模式才能满足我的需求。或者我错了吗?

请参阅Neo4j谷歌小组的讨论:https://groups.google.com/d/msg/neo4j/UuW-cGYJFLw/oThWdGvRuT4J - Michael Hunger
1个回答

4
首先,您正在寻找的复杂权限系统有一个标准规范称为 RBAC(基于角色的访问控制)RBAC。我已经在 SQL 中实现了各种简单和复杂的 RBAC 模型。在关系数量超过百万时,SQL 实现在普通硬件上不快。读取是即时的,但由于需要重复记录以提供快速读取,因此写入很慢。
最初,当我设计权限系统时,我根据 RBAC 规范在纸上“画”出来。输出确实是一个图形。因此,在两年的生产使用后,我考虑切换到本地图形数据库。
Neof4j 是一种流行的解决方案,但一些重要的客户似乎对其弱的集群和复制系统感到不满。因此,请查看 OrientDB(请参阅 OrientDB vs Neo4j)。
您上面提到过,“在Neo4j数组中无法存储复杂类型”,而OrientDB则通过自定义数据类型解决了这个问题。虽然我个人还没有尝试过,但计划在迁移我们的生产数据后进行测试。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接