DDDとアクセス制御について読んだところ、次の2つの意見の間に矛盾が見つかりました。
これに関するベストプラクティスを探しています。では、ドメイン駆動設計によるアクセス制御ロジックをどこに配置すればよいのでしょうか。また、どのように実装する必要がありますか
(DDD + CQRS + ESにより具体的になります。)
私はそれがビジネスロジックに近いところにあるべきだと思います。たとえば、ユーザーストーリーは次のようなものです。
ユーザーは、ユーザー名、趣味のリスト、CVなどを送信することにより、自分のプロファイルを編集できます。
ユーザーストーリーに基づいて、ドメインモデルとサービスを実装します。次に例を示します。
UserService
editProfile(EditUserProfileCommand command)
User user = userRepository.getOneById(command.id)
user.changeName(command.name)
user.changeHobbies(command.hobbies)
user.changeCV(command.cv)
UserRepository
User getOneById(id)
User
changeName(String name)
changeHobbies(String[] hobbies)
changeCV(String cv)
これは問題ありませんが、ストーリーのHIS profile
部分はどこにありますか?
これは明らかに属性ベースのアクセス制御です。次のようなルールを書く必要があるからです。
deny all, but if subject.id = resource.owner.id then grant access
しかし、このルールをどこに適用し、どのように実装する必要があるのでしょうか。
では、アクセス制御ロジックはどこに配置すればよいですか?
これによると、 https://softwareengineering.stackexchange.com/a/71883/65755UserService.editProfile()
の呼び出しの直前にポリシー実施ポイントを置く必要があります。
同じ結論に達しました。複数のUIがあるとコードの繰り返しが発生するため、UIに含めることはできません。ドメインイベントが作成される前でなければなりません。なぜなら、システムですでに何かを行っていることを示しているからです。したがって、ドメインオブジェクトまたはそれらのドメインオブジェクトを使用するサービスへのアクセスを制限できます。 CQRSでは、読み取りモデルによるドメインオブジェクトは必要ありません。サービスだけなので、一般的なソリューションが必要な場合は、サービスへのアクセスを制限する必要があります。すべてのサービス操作の最初にアクセス決定を置くことができますが、それはgrant all, deny x
セキュリティ対策パターン。
どのように実装すればよいですか?
これは、ドメインに適合するアクセス制御モデルに依存するため、ユーザーストーリーに依存します。アクセス決定により、通常はアクセス要求を送信し、代わりに許可を待ちます。アクセス要求には通常、サブジェクト、リソース、操作、環境の部分があります。したがって、サブジェクトには、環境内のリソースに対して操作を実行するための権限が必要です。最初にサブジェクトを識別し、次にそれを認証します。その後、承認が行われ、アクセス要求がアクセスポリシーに適合しているかどうかが確認されます。すべてのアクセス制御モデルは同じように機能します。 Ofc。これらの手順の一部が不足する可能性がありますが、それは問題ではありません...
アクセス制御モデルの短いリストを作成しました。私はルール、ポリシーをアノテーションに入れましたが、通常、十分に保守可能なシステムが必要な場合は、おそらくXACML形式でデータベースに保存する必要があります...
IDベースのアクセス制御(IBAC)により、ID-アクセス許可ストレージ(アクセス制御リスト、機能リスト、アクセス制御マトリックス)があります。したがって、たとえばアクセス制御リストによって、権限を持つことができるユーザーまたはグループのリストを保存します。
UserService
@AccessControlList[inf3rno]
editProfile(EditUserProfileCommand command)
ラティスベースのアクセス制御(LBAC)により、サブジェクトにはクリアランスレベルがあり、リソースには必要なクリアランスレベルがあり、どのレベルが高いかを確認します...
@posseses[level=5]
inf3rno
UserService
@requires(level>=3)
editProfile(EditUserProfileCommand command)
役割ベースのアクセス制御(RBAC)により、サブジェクトの役割を定義し、実際の役割を担うサブジェクトにアクセス許可を付与します。
@roles[admin]
inf3rno
UserService
@requires(role=admin)
editProfile(EditUserProfileCommand command)
属性ベースのアクセス制御(ABAC)により、サブジェクト、リソース、および環境の属性を定義し、それらに基づいてポリシーを記述します。
@attributes[roles=[admin]]
inf3rno
UserService
@policy(subject.role=admin or resource.owner.id = subject.id)
editProfile(EditUserProfileCommand command)
@attribute(owner)
Subject getOwner(EditUserProfileCommand command)
ポリシーベースのアクセス制御(PBAC)により、ポリシーを他に割り当てず、スタンドアロンです。
@attributes[roles=[admin]]
inf3rno
UserService
editProfile(EditUserProfileCommand command)
deleteProfile(DeleteUserProfileCommand command)
@attribute(owner)
Subject getOwner(EditUserProfileCommand command)
@permission(UserService.editProfile, UserService.deleteProfile)
@criteria(subject.role=admin or resource.owner.id = subject.id)
WriteUserServicePolicy
リスク適応型アクセスコントロール(RAdAC)によって、被験者の相対的なリスクプロファイルと手術のリスクレベルに基づいて決定を下します。これは私が思うルールでは説明できません。私は実装について確信が持てません。おそらくこれがポイントシステムでstackoverflowが使用するものです。
承認ベースのアクセス制御(ZBAC)では、識別と認証は行わず、代わりに識別要素にアクセス許可を割り当てます。たとえば、誰かがトークンを送信した場合、彼女はサービスにアクセスできます。その他はすべて、以前のソリューションと同様です。たとえばABACの場合:
@attributes[roles=[editor]]
token:2683fraicfv8a2zuisbkcaac
ArticleService
@policy(subject.role=editor)
editArticle(EditArticleCommand command)
ですから、2683fraicfv8a2zuisbkcaac
トークンはサービスを使用できます。
等々...
他にも多くのモデルがあり、最適なものは常にお客様のニーズに依存します。
要約すると
- "security concerns should be handled outside the domain"
- "access control requirements are domain specific"
セキュリティはドメインモデルの一部ではないため、どちらも正しい可能性がありますが、その実装はドメインモデルとアプリケーションロジックに依存します。
2年後に編集2016-09-05
私はDDDの初心者として自分の質問に答えたので、Vaughn Vernonから Implementing Domain-Driven Design を読みました。話題の面白い本でした。ここからの引用です:
これは、新しいBounded Context-Identity and Access Context-を構成し、標準のDDD統合技術を通じて他のBounded Contextによって使用されます。消費するコンテキストにとって、アイデンティティおよびアクセスコンテキストは汎用サブドメインです。製品の名前はIdOvationになります。
したがって、Vernonによると、アクセス制御を汎用サブドメインに移動するためのおそらく最良のソリューションです。