我正在使用Java / Spring和至少2个不同的数据库构建一个相当复杂的Web应用程序:
下一步是授权。基于简单角色的授权是不够的,因为应允许/禁止用户查看/修改不同的资源。虽然我想到了ACL。
最常见的简单ACL表可能如下所示:
TABLE | FIELDS
-------+--------------
class | id, className
object | id, class_id, objectId
acl | id, object_id, user_id, permissionBitMask (crud)
但不幸的是,这还不足以满足我的需求:(
。
我还需要:
如果我结合所有这些方面,我得到以下表格结构:
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优势:
->
no JOIN
{
class: ClassName,
object: ObjectId,
parent: RelationToParentNode,
user: UserId,
role: RoleId,
grantedPermissions: [Permission1, Permission2, ...]
}
(每个权限,未在数组中列出,自动未被授予。无法在Neo4j数组中存储复杂类型,因此无法存储类似{{1}的内容}})
当然,也可以将权限和类存储为单独的节点,并将它们全部链接在一起。但我不知道Neo4j有什么更好的方法。
有关于此的任何想法吗?有没有开箱即用的解决方案?也许有理由将MongoDB用于ACL?
我读过有关XACML和OAuth(2)的信息,但两者似乎都需要一个额外的ACL模式来完成我需要的工作。或者我错了吗?
答案 0 :(得分:2)
首先,您正在寻找的复杂权限系统有一个名为RBAC的标准规范(基于角色的访问控制)。我在SQL中实现了各种简单和复杂的RBAC模型。工作正常,当关系数量超过百万时,SQL实现在商品硬件上并不快。读取是即时的,但由于重复记录以提供快速读取的繁重工作,写入速度很慢。
最初,当我设计了权限系统时,我确实是在"画出"它基于RBAC规范的纸张。输出实际上是图形。因此,经过两年的生产使用,我正在考虑切换到原生图数据库。
Neof4j是一种流行的解决方案,但由于其弱集群和复制系统,一些重要客户似乎对此不满意。所以看看OrientDB(见OrientDB vs Neo4j)。
您已经在上面提到过"它无法在Neo4j阵列中存储复杂类型"。 OrientDB自豪地用自定义数据类型解决了这个问题。我还没有亲自尝试过,但计划在迁移我们的生产数据后进行测试。