复杂应用程序的高性能ACL模式(RDBMS,图形数据库?)

时间:2014-07-12 07:52:19

标签: permissions neo4j authorization acl rdbms

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

  • 主数据的RDBMS
  • MongoDB for files(通过GridFS)和其他数据CLOBs / JSON / etc。

下一步是授权。基于简单角色的授权是不够的,因为应允许/禁止用户查看/修改不同的资源。虽然我想到了ACL。

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

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

但不幸的是,这还不足以满足我的需求:(

我还需要:

  • 角色
    • 每个用户可以拥有多个角色,
    • ACL条目也可以属于角色
  • 更多权限
    • 例如:每个项目可以有多个任务可以修改项目详细信息的用户不允许为此项目创建新任务。因此必须有单独的许可。
  • 不同类型的ObjectId
    • RDBMS表将使用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

当然我可以将acl表拆分为2个表(1. object + user,2。object + role),但我认为这并不重要。

“objectId”将是一个简单的VARCHAR,我的应用程序必须将它从/转换为String。另外,我的不同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条目。

这不是真正的高效。那有什么选择呢?我的想法:

  • 不同的数据库架构(任何想法!?)
  • 图形数据库,如Neo4j。

Neo4j优势:

  • 使用权限条目查找第一个父项是此DB的简单任务
  • 可以在ACL条目中存储一组权限-> no JOIN
  • 基本上我可以将所有信息存储在一个节点中:

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

(每个权限,未在数组中列出,自动未被授予。无法在Neo4j数组中存储复杂类型,因此无法存储类似{{1}的内容}})

当然,也可以将权限和类存储为单独的节点,并将它们全部链接在一起。但我不知道Neo4j有什么更好的方法。


有关于此的任何想法吗?有没有开箱即用的解决方案?也许有理由将MongoDB用于ACL?

我读过有关XACML和OAuth(2)的信息,但两者似乎都需要一个额外的ACL模式来完成我需要的工作。或者我错了吗?

1 个答案:

答案 0 :(得分:2)

首先,您正在寻找的复杂权限系统有一个名为RBAC的标准规范(基于角色的访问控制)。我在SQL中实现了各种简单和复杂的RBAC模型。工作正常,当关系数量超过百万时,SQL实现在商品硬件上并不快。读取是即时的,但由于重复记录以提供快速读取的繁重工作,写入速度很慢。

最初,当我设计了权限系统时,我确实是在"画出"它基于RBAC规范的纸张。输出实际上是图形。因此,经过两年的生产使用,我正在考虑切换到原生图数据库。

Neof4j是一种流行的解决方案,但由于其弱集群和复制系统,一些重要客户似乎对此不满意。所以看看OrientDB(见OrientDB vs Neo4j)。

您已经在上面提到过"它无法在Neo4j阵列中存储复杂类型"。 OrientDB自豪地用自定义数据类型解决了这个问题。我还没有亲自尝试过,但计划在迁移我们的生产数据后进行测试。