首页 文章

基于值组合的安全性哈希密钥

提问于
浏览
2

我在MongoDB中有大量的记录/文档,我需要通过每个文档列表中的值组合来限制对项目的访问 .

想象一下,安全性的可能单个值是[1,2,3] .

记录可以是这些记录的任意组合,即:()(1,)(2,)(3,)(1,2)(1,3)(2,3)(1,2,3)

  • 有权访问[1]的用户只能看到有()&(1)的记录

  • 有权访问[2]的用户只能看到有()和(2)的记录

  • 有权访问[1,2]的用户只能看到有(),(1),(2),(1,2)的记录

  • 只有能够访问[1,2,3]的用户才能看到所有记录

现在,在数据库的入口点,我知道用户的访问权限,例如[1,2,3] . 但我不能轻易(特别是索引)查看记录以检索用户有权访问的所有值 .

创建一个函数为每条记录创建唯一的哈希值非常简单:

def hash_combination(input):
    return hash(frozenset(input))

这将为每条记录提供一个唯一的密钥,我们可以将其用作过滤器 . 然后为用户获取所有可能的密钥也很容易:

from itertools import chain, combinations

def powerset(iterable):
    "powerset([1,2,3]) --> () (1,) (2,) (3,) (1,2) (1,3) (2,3) (1,2,3)"
    s = list(iterable)
    return chain.from_iterable(combinations(s, r) for r in range(len(s) + 1))

def hash_powerset(iterable):
    return [hash(frozenset(x)) for x in powerset(iterable)]

但是组合的可能唯一输入的实际列表可能非常大(50),从而产生了太大而不实用的因素 .

我只能想到两种可能的解决方案 . 第一是逐行检查:

security_list = (1, 2, 3)
for row in db.collection.find():
    # check security
    if any(x not in security_list for x in row['row_security']):
        continue
    # security passed
    pass

但这是一个性能杀手 . 另一个是将选择反转为“我们看不到的东西”:

unique_list = (1, 2, 3, 4, 5)
security_list = (1, 2, 3)
not_allowed_list = (x for x in unique_list if x not in security_list)
for row in db.collection.find({'row_security': {'$nin': not_allowed_list}}):
    # security passed
    pass

但这也是mongodb无法索引的操作(可能是因为我现在遇到的类似原因),所以仍然不利于性能 . 比以前的选项更好(因为你避免转换为python对象作为瓶颈),但仍然不是很好

我们案例的一些细节:

  • 我们总是知道用户的安全列表

  • 我们总是知道可能的唯一值列表(这可能很大)

  • python 2.7,mongodb 3.0

还有其他方法吗?什么是最好的方法来解决这个问题?

亲切的问候,

CARST

1 回答

  • 0

    根据Python Zen,您首先要发明一个干净的解决方案,然后在实际看到它需要优化时才进行优化 .

    因此,正如您所看到的,这里实际上有两个任务:1)计算出一般算法,2)优化特定环境的算法 .


    你的任务的核心是:

    • 鉴于:

    • 每条记录都有一组标记(1,2,3),标记为访问它所需的"privileges/clearance levels"

    • 用户也有一组相同的标志,指定其清除级别

    • 问题:

    • 返回用户有权访问的所有记录

    既然它是这样制定的,答案是微不足道的:

    result = {record for record in set_ if user.mask >= record.mask}
    

    现在,对于第二个任务,您需要检查MongoDB有效执行哪些操作,并找出如何使用它们来实现此操作 .

相关问题