2017-01-13 4 views
2

私はMongoDBに大きなレコードセット/ドキュメントを持っており、各ドキュメントのリストにある値の組み合わせによってアイテムへのアクセスを制限する必要があります。値の組み合わせに基づくセキュリティハッシュキー

セキュリティの可能な値は[1、2、3]であるとします。

レコードはこれらの任意の組み合わせを持つことができます。 (1、)(2、)(1,3)(2,3) 2,3)

  • [1]のみ(持つレコードを参照することができるであろうへのアクセス権を持つユーザ)&(1)
  • [2]へのアクセス権を持つユーザは、あろう[1、2]にアクセスできるユーザーは、(1)、(2)、(3)、(4)を持つレコードのみを表示できます。 、(1,2)
  • 私は、ユーザーのアクセスは、例えば、あるものを知っているデータベースへのエントリポイントですべてのレコード今

を見ることができるだろう[3、1、2]にアクセスできるユーザーのみ[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+)非常に大きくなることができますし、ユーザーのために可能なすべてのキーを取得することは、あまりにも簡単です。実用的。

2つの解決策しか考えられません。 1行目は行ごとのチェックです:

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

+0

これは* Code Review *(http://codereview.stackexchange.com/)のための良い質問のように見えます。 –

+1

正直言って、私はどちらが一番良いかを選択することが時々難しいです。しかし、私は、特定のプログラミング問題のstackoverflowを指しているhttp://meta.stackexchange.com/questions/129598/which-computer-science-programming-stack-exchange-do-i-post-inに基づいています。ソフトウェアアルゴリズム「 – Carst

+1

私は[__acl__](https://stackoverflow.com/questions/tagged/acl+mongodb)があなたが発明しているシステムの適切な名前だと思います。 – robyschek

答えて

0

Pythonの禅によると、あなたは最初あなたが実際にそれが最適化を必要としていることを見れば、それをを最適化して行くだけにしてきれいなソリューションとを発明。

実際にはという2つのタスクがここにあります:1)一般的なアルゴリズムを実行します.2)特定の環境に対してアルゴリズムを最適化します。あなたの仕事の中核に


です:

考える
    • 各レコードは、「権限/クリアランスレベルをマークするフラグのセット(1,2,3)を持っています"アクセスする必要があります
    • ユーザーにもクリアランスレベルを指定して同じフラグが設定されています
  • 問題:

    • 復帰ユーザーが

へのアクセス権を持つすべてのレコードは、今では、このように定式化だと、答えは簡単です:

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

今、2番目のタスクでは、 dを使ってMongoDBがどの操作を効率的に実行しているかを調べ、それを使ってこの操作を実装する方法を見つけます。

+0

こんにちは、Python Zenと完全に同意しました。私は両方のソリューションが機能的に機能することを強調しなければなりません。最初の解決策は、基本的にあなたの提案の現実のmongodb版です。私の質問のタイトルはおそらくもっと良いと言えるでしょう。 問題は、アルゴリズムの種類とマスクの包含/除外の方法がここで非常に多く、それぞれのソリューションの後にパフォーマンスの部分に潜んでいる理由です。これにより、理論的に機能的な解決法が両方とも実用的に実現できなくなる: – Carst

関連する問題