レコヌドオブゞェクトのレベルでの柔軟なアクセス制埡

みなさんこんにちは


Djangoベヌスのプロゞェクトでは、異なるナヌザヌが同じモデル内の個々のオブゞェクトにアクセスできない堎合、たたはその逆の堎合、レコヌドオブゞェクトのレベルで柔軟なアクセス制埡を䜿甚するこずがよくありたす。


私たちのプロゞェクトで必芁なデヌタアクセスポリシヌ、適切な既補のシステムがなかった理由、レコヌドレベルでの新しいアクセス制埡システムがどのように登堎したかを正確に説明したいず思いたす。


最も现心の泚意を払うために、システムデバむス、その内郚ロゞック、およびその凊理方法の詳现を以䞋に瀺したす。


埅おない人のために


Django-Accessプロゞェクト


既存のシステム


ゞャンガにはすでにいく぀かの゚ントリヌレベルのアクセス制埡システムがありたす。 最も有名で安定したシステムはDjango-GuardianずDjango-Authorityです。


ゞャンゎ保護者


最初のシステムであるDjango-Guardianでは、ナヌザヌずナヌザヌが察話できるオブゞェクトずの間に、型なしの関係぀たり、デヌタベヌス内のレコヌドを䜜成する必芁がありたす。 ナヌザヌずオブゞェクトの各ペアには、このような個別の暩利レコヌドが必芁です。 デヌタベヌス内のこれらのレコヌドの数は、そのようなシステムでアクセス暩が芏制されおいるナヌザヌずオブゞェクトの数の積ずしお蚈算されたす。


プロゞェクトデヌタベヌス内のナヌザヌおよび管理オブゞェクトの数が無制限の堎合、暩利レコヌドの数は非垞に急速に増加するこずを理解するのは簡単です。 たた、ナヌザヌを削陀する際のこれらのレコヌドの削陀の管理、ナヌザヌのアクセス領域を倉曎したり、あるナヌザヌの可芖性から別のナヌザヌの可芖性にオブゞェクトを移動した堎合の暩利レコヌドのグルヌプ線集により、プロゞェクトでDjango-Guardianを䜿甚する可胜性は䜎くなりたした。


ゞャンゎ暩嚁


2番目のシステムDjango-Authorityは 、共通のタグを介しおナヌザヌず管理察象゚ンティティずの関係を確立するこずにより、最初のシステムの問題を解決しようずしたす。 このような各タグは、ナヌザヌたたはコントロヌルオブゞェクトに関連付けられたタグテヌブル内の゚ントリです。 同じ名前のタグが特定のナヌザヌず特定のオブゞェクトに関連付けられおいる堎合、このナヌザヌはこのコントロヌルオブゞェクトにアクセスできるず芋なされたす。


この堎合のタグ゚ントリの数は倧幅に少なくなり、ナヌザヌずオブゞェクトの数の合蚈に比䟋したすが、これは蚱容範囲です。 ただし、このようなシステムでは、非垞に珍しいタグ呜名システムを維持する必芁がありたす。 実際には、そのような名前はそれぞれ「スコヌプ」に察応したす可芖性など。 このスコヌプに属するすべおのオブゞェクトには、このスコヌプにアクセスできるナヌザヌに加えお、察応するタグがありたす。


Django-Guardianでは根本的に解決されおいないパフォヌマンスの問題は、Django-Authorityではかなり蚱容できる範囲で解決されおいたす。


残念ながら、このシステムの開発は長い間䞭断されおいたす。 確立された関係に埓っおアクセスを制埡する管理パネルずの統合はありたせん。 管理者ベヌスのアプリケヌションむンタヌフェむスを開発したかったのですが、このシステムを䜿甚しお、ずにかく管理者を線集する必芁がありたした。


ただ管理パネルを線集する必芁があるので、独自のアクセス制埡システムを䜜成しおみたせんか


新しいシステムに必芁なもの


配垃する暩利


圓初、私たちのシステムは、オブゞェクトの可芖性を決定するこずにのみ焊点を圓お、それらの倚くを「氎平に」分割したした。 可芖性に陥ったオブゞェクトを管理する暩利は、モデルタむプに応じお、ゞャンガの䌝統的な暩利システムに埓っお「垂盎に」分配されたした。


このような分離は、ある点たではたったく受け入れられるものでしたが、アクセスを「クロス」に分散する必芁がある堎合、システムが粗すぎるこずが刀明したした。 本圓に。 ナヌザヌオブゞェクトぞのアクセスを配垃したしょう。 ナヌザヌは自分のグルヌプの管理者であり、このグルヌプからナヌザヌレコヌドを線集および削陀するこずもできたす。 䞀方、グルヌプの管理者であるナヌザヌは、他のグルヌプの通垞のナヌザヌになりたいず考えおいたす。 ただし、管理者はレコヌドに同じアクセス暩を持っおいるため、レコヌドが衚瀺されるずすぐに、どのグルヌプでも関係ありたせん。


したがっお、「氎平方向」に、オブゞェクトの可芖性だけでなく、オブゞェクトに察しお実行される操䜜の党範囲を制埡する必芁があるこずが明らかになりたした。 埓来、オブゞェクトで最も䞀般的で䞀般的に䜿甚される4皮類のアクションが定矩されおおり、頭字語CRUD䜜成、読み取り、曎新、削陀によっお組み合わされるこずもありたす。



暩利定矩セット


オブゞェクトのサブセットに察する特定のアクションの蚱可を芏制する必芁がありたす。 Jungでオブゞェクトの特定のサブセットを操䜜する最も自然で効率的な方法は、 QuerySetを䜿甚するこずです。 オブゞェクトの特定のサブセットを凊理する必芁がある堎合はい぀でも䜿甚したす。


ただし、 QuerySetは、必芁なセットオプションの1぀、぀たり過去および未来のすべおのオブゞェクトを含む 、このモデルのすべおのオブゞェクトのセットを蚘述したせん。 実際、このセットはモデル自䜓によっお決定され、Djangoの「䌝統的な」暩利が定矩される唯䞀の皮類のセットです。 実際、 QuerySet基づいおアクセス暩をチェックしおいるずしたしょう。 空のQuerySetを受け取ったので、少なくずも䞀郚のオブゞェクトを衚瀺するための十分な暩限がないため、たたはデヌタベヌス内にオブゞェクトが圢成されおいないために、オブゞェクトがその䞭にあるかどうかを確認できたせん芋るために。


したがっお、 QuerySetを䜿甚しお特定のオブゞェクトのセットを定矩するか、モデルを䜿甚しお、これたでに存圚した、たたは将来䜜成されたこのモデルのすべおのオブゞェクトを念頭に眮いお、暩限が定矩されるオブゞェクトのQuerySetを定矩したす。


倉曎する必芁があるもの


管理者


実際には、䞊蚘のすべおを管理パネルに適甚する必芁がありたす。 衚瀺されおいるオブゞェクトのリストが衚瀺され、確立された暩限に応じお、オブゞェクトの远加、線集、たたは削陀が蚱可および犁止されたす。


既存の管理者の動䜜を倉曎するには、それらのメ゜ッドの䞀郚の代わりにたたは远加しお、新しいアクセス制埡システムによっお課せられた制限ず暩限を考慮したコヌドが呌び出されるこずを確認する必芁がありたす。 これは、 Mixinプログラミングテンプレヌトを䜿甚しお行うのが最適です。これは、基本クラスのリストの最䞊郚で、他の基本クラスからのメ゜ッド呌び出しをむンタヌセプトするクラスを定矩したす。


埓来の蚱可システム


QuerySetで定矩されたサブセットだけでなく、モデルQuerySetで定矩されたこのタむプのすべおのオブゞェクトのセットに察する暩限も決定する必芁がありたす。 したがっお、プロゞェクトで䜿甚できるたたは䜿甚できない 可胜性の 1぀ずしお、 Permissionオブゞェクトに基づくゞャンガの暩利の「䌝統的な」モデルを定矩したす。


暩利を説明すべき堎所


最初は、暩利の配垃方法に関する情報を投皿するのに最適な堎所はモデルだず思われたす。 叀いシステムはこれにオブゞェクトマネヌゞャを䜿甚したした。これは、モデルオブゞェクトぞのアクセスを提䟛し、モデルクラスプロパティオブゞェクト の定矩に挿入するこずで再定矩できるDjangaのものです。


ただし、刀明したように、この方法にはいく぀かの欠点がありたす。


たず、モデルオブゞェクトにアクセスする方法は、Django アプリケヌション むンストヌルされたパッケヌゞから倉曎せずに䜿甚されるこずが倚いサブシステムのプロパティではなく、 プロゞェクト党䜓のプロパティです。 同じアプリケヌションパッケヌゞが異なるプロゞェクトで䜿甚される堎合、このアプリケヌションのモデルオブゞェクトぞのアクセスは、これらのプロゞェクトで異なる方法で定矩される可胜性が非垞に高くなりたす。


第二に、アクセスルヌルを定矩するず、いく぀かのアプリケヌションたずえば、 auth の境界を越えるこずができたすほずんどの堎合そうなりたす。 それらの1぀で説明されおいるため、定矩には別のアプリケヌションパッケヌゞずの䞍必芁な通信が必芁になる堎合がありたす。


したがっお、プロゞェクトには、個々のアプリケヌションずは無関係に、プロゞェクトのさたざたなオブゞェクトパッケヌゞぞのアクセスルヌルのレゞストリが必芁です。 このレゞストリは、モデルの䜿甚時にむンポヌトされるさたざたなモゞュヌルから構造的に取り蟌むこずができたす。 このようなレゞストリには、独自のモデルだけでなく、プロゞェクトに関連するすべおのアプリケヌションパッケヌゞからむンポヌトされたモデルのアクセスルヌルの定矩が含たれたす。


暩利を蚘述する方法


この問題に察する倱敗した、狭すぎる解決策は、既存のパッケヌゞに䞍必芁な制限をもたらしたした。


他のパッケヌゞずは異なり、この目的のためだけに蚭蚈されたいく぀かの特別なモデルの助けを借りおではなく、プロゞェクトずそのリク゚ストに既に存圚するモデルに適甚されるコヌドの助けを借りお暩利を説明したす。


幞いなこずに、コヌドはメ゜ッドたたは関数内だけでなく、ラムダ匏内にも配眮できたす。 このメ゜ッドを䜿甚しお、最も明癜でシンプルで頻繁に䜿甚されるアクセス制限ルヌルを説明したす。


アクセス制限ルヌルの実行のコンテキスト


通垞、アクセスは「珟圚の」ナヌザヌに察しお制限されたす。 ただし、アクセスが制限されおいるコンテキスト芁玠は珟圚のナヌザヌだけではないこずを忘れおはなりたせん。 「珟圚のビゞネス」、遞択した囜、蚀語、たたはアクセスを提䟛する決定時に関連するその他の芁因がアクセスに圱響する可胜性がありたす。


したがっお、アクセスルヌルを定矩するコヌドは、アクセス制限のコンテキストずしお、 リク゚スト党䜓 Request を受け取りたす。 このコンテキストから正確に制限の察象ずなるものは、このコヌド自䜓によっお決定されるべきです。


システムクラス構造


アクセスマネヌゞャヌ


システムの機胜を定矩する䞭心的なクラスは、アクセスマネヌゞャヌmanagers.AccessManagerクラスです。 䞀方では、さたざたなオブゞェクトのアクセス制限ルヌルを定矩するプラグむンオブゞェクトを登録できたす。他方では、このクラスのオブゞェクトを䜿甚しお、プログラムでそのような定矩が必芁な堎合にオブゞェクトおよびセットに関する暩限を決定する操䜜を実行したす。


アクセス制限ルヌルを䜜成する


アクセス制限ルヌルは、プラグむンオブゞェクトを䜜成および登録するこずにより䜜成されたす。


マネヌゞャヌクラスのメ゜ッドregister/unregister_plugin(s)䜿甚するず、プラグむンのレゞストリを操䜜できたす。 1぀のモデルクラスの耇数のプラグむンがレゞストリに远加されるこずはありたせん。 register_pluginsメ゜ッドは、モデルがキヌずしお機胜する蟞曞を受け取り、 register_pluginはモデルクラスずプラグむンオブゞェクトを個別のパラメヌタヌずしお受け取りたす。


ヘルパヌマネヌゞャヌクラスメ゜ッドget_default_pluginは、デフォルトで登録枈みプラグむンを返し、 get_default_pluginは枡されたモデルクラスに登録されたプラグむンを探したす。 モデルのプラグむンを怜玢する堎合、継承が考慮されたすが、モデルではないクラスは怜玢から陀倖されたす。 モデルのプラグむンが芋぀からない堎合、デフォルトのプラグむンが返されたす。


pluginsモゞュヌルの定矩枈みプラグむンクラスには、他のプラグむンを結合するApplyAblePlugin 、 CheckAblePluginおよびCheckAblePluginアクセス制限ルヌルを動的に定矩するプラグむン、およびCheckAblePluginオブゞェクトの分析に基づいた埓来のアクセス制限ルヌルず同様のアクセス制限ルヌルを実装するDjangoAccessPluginが含たれたす。


アクセス制限チェック


動的に定矩された属性をapply_somethingするず、 check_somethingアクセスマネヌゞャヌでapply_somethingメ゜ッドずapply_somethingメ゜ッドを呌び出すsomethingができたす。ここで、 somethingが任意の有効な名前です。 この名前は、システムから芁求される胜力- 胜力 -の名前です。 たずえば、衚瀺暩 visible胜力を取埗するには、 check_visibleおよびappy_visibleメ゜ッドcheck_visible appy_visibleたす。


check_somethingメ゜ッドはモデルを受け取り、それに関連する機胜の制限を決定し、 appy_somethingはappy_somethingメ゜ッドに枡され、メ゜ッドはこのリク゚ストのオブゞェクトのリストに関する機胜の制限を決定したす。


マネヌゞャヌは、登録されたプラグむンを怜玢し、それから、たたはデフォルトでプラグむンから同様の方法で芁求したす。 欠萜しおいるメ゜ッドずは、芁求されたセットのすべおのオブゞェクトに関しお、指定された胜力で芁求されたアクションを解決するこずを意味したす。 プラグむンが芋぀かった堎合、チェックしたす。


モデル党䜓ぞのアクセスを制限する


モデル党䜓ぞのアクセスは、 check_プレフィックスを持぀プラグむンメ゜ッドによっお制限されたす。 モデルず、暩利チェックのコンテキストを定矩するRequestオブゞェクトがメ゜ッドに枡されたす。 メ゜ッドがFalseを返す堎合、アクセスは拒吊されたす。 アクセスを蚱可するために、通垞は蟞曞が返されたす。これにより、 CompoundPlugin凊理するずきに返された倀を組み合わせるこずができたす。 倀を返すこのやや予期しない方法により、 check_appendableを远加するためのアクセスをリク゚ストするずきにそれらを䜿甚できたす。


個々のオブゞェクトぞのアクセスを制限する


個々のオブゞェクトぞのアクセス制限の分析は、指定されたアクセスが蚱可されおいるオブゞェクトのみを残しお、 QuerySetク゚リにフィルタヌを課すこずを意味したす。


このオヌバヌレむは、 apply_プレフィックスを付けたプラグむンメ゜ッドによっお実行されたす。 QuerySetず、暩利チェックのコンテキストを定矩するRequestオブゞェクトがメ゜ッドに枡されたす。 このメ゜ッドは、枡されたQuerySetフィルタヌを適甚し、指定されたコンテキストの指定されたアクセスメ゜ッドを蚱可するオブゞェクトのみにオブゞェクトのセットを制限し、フィルタヌされたQuerySetを返したす。


暙準チェック


システムは、システムオブゞェクトに関しおコンテキストから次の機胜をチェックしたす。



同時に、特定のオブゞェクトに察するチェックはcheck_appendableためcheck_appendableな機胜はcheck_appendableそれぞれcheck_appendableメ゜ッドを䜿甚しお、モデル党䜓に​​関しおのみチェックされたす。それらはすでに䜜成されおいたす。


残りの胜力は、モデル党䜓ずオブゞェクトの特定のリストの䞡方に関しおテストされたす。 合蚈で、暙準チェックの堎合、次のプラグむンメ゜ッドが呌び出されたす定矩されおいる堎合。



カスタムチェック


どのアプリケヌションでもAccessManagerオブゞェクトを䜜成し、暙準機胜ず非暙準機胜の䞡方をチェックするように芁求できたす。 これを行うために、アプリケヌションはcheck_たたはcheck_ apply_ず、芁求された胜力に察応するサフィックスを持぀メ゜ッドをリク゚ストしたす。


芁求された胜力に察応するメ゜ッドが芋぀かったプラグむンで定矩されおいない堎合、利甚可胜ず芋なされたす。 この堎合のcheck_メ゜ッドは空の蟞曞を返し、 check_は倉曎されおいないQuerySetです。


管理者


adminモゞュヌルには、暙準のDzhangovskoy管理パネルの任意のクラスず混合できる特別なクラスAccessControlMixinが含たれおいAccessControlMixin 。 このクラスは、オブゞェクトぞのアクセス順序の決定に関䞎するメ゜ッドをオヌバヌラむドし、プロゞェクトに蚭定されたアクセス制限ルヌルに埓っおアクセスを制限したす。


管理パネルをれロから構築するために、 AccessModelAdmin 、 AccessTabularInlineおよびAccessStackedInlineクラスも定矩されおいたす。これらのクラスは、 AccessTabularInlineずたったく同じ方法で䜿甚できたす。 本質的に、これらのクラスはAccessControlMixinず察応するAccessControlMixinクラスの玔粋な組み合わせです。


䟋


パッケヌゞの機胜を瀺すために、パッケヌゞの゜ヌスコヌドの䞀郚である䟋を䜿甚したす。


この䟋では、暙準パッケヌゞsomeappモデルを䜿甚し、独自の远加アプリケヌションsomeappを䜿甚しお、モデルの2぀のクラスを定矩しおいたす。



䟋では、次のアクセススキヌムを定矩しおいたす。



グルヌプの远加アクセスルヌルは、远加時に䜜成者がグルヌプに含たれるこずも決定したす。 これは、新しく䜜成されたグルヌプが远加埌に䜜成者が利甚できるようにするために行われたす。


したがっお、この䟋では、パッケヌゞの機胜を䜿甚し、最小限の远加コヌドを远加するこずにより、個々のナヌザヌ機胜ず共通スペヌスの䞡方ぞのアクセスが制埡された快適で安党な環境が䜜成されたす。


おわりに


Django-Accessパッケヌゞのアクセス制限ルヌルの機胜定矩により、アクセス制埡のための耇雑な任意ルヌルの蚭定が簡単になり、コヌドでプロゞェクトやレコヌドでデヌタベヌスを乱雑にする远加゚ンティティの䜜成を回避できたす。


プロゞェクトの開発に参加し、バグを探し、問題を䜜成したす。 プルリク゚ストは倧歓迎です。



Source: https://habr.com/ru/post/J341496/


All Articles