セキュリティ

PowerPortalsProは、 テーブル レベルと レコードレベルの両方でアクセスを管理できる、柔軟でコード駆動型のセキュリティモデルを提供します。セキュリティは、権限ハンドラークラスを作成し、依存性インジェクションコンテナに登録することで実装されます。

概要

必要な制御レベルに応じて実装できるインターフェースは2つあります:

ヒント

テーブルレベルのチェック(例:「認証済みのユーザーがこのテーブルを読める」など)だけが必要な場合は、 ITablePermissionHandlerを使いましょう。レコードレベルのロジック(例:「ユーザーは自分が所有するレコードしか削除できない」)が必要な場合は ITableRecordPermissionHandlerを使います。

ベストプラクティスは、ソースからフィルタリングすること

許可ハンドラーはアクセスを 強制します が、 フィルタリングの代わりにはなりません。レコードレベルのハンドラは、Dataverseからレコードのページを取得し た後 に動作するため、行を隠すためにそれらに頼ることはグリッドページング(50ページで表示される数が少なくなることもあります)や総数を歪め、行を取得して破棄するクエリの無駄を生みます。データを現在のユーザーにスコープ化する必要がある場合は、クエリレベルでフィルタリングを行い、 IFetchXmlQueryFilterInterceptor (下記参照)や現在のユーザーを考慮したカスタムビューで、Dataverseはユーザーが見るべき行だけを返し、ページを正確にグリッド化します。許可ハンドラーは執行保証として使っておきましょう。

Dataverse-Native Security (プレビュー)

今後推奨されるセキュリティモデルでは、Power Pagesの統合されたDataverseセキュリティ機能を基盤に、Dataverse自身がポータルユーザーに対してセキュリティを強制できるようになります。コード内で権限ハンドラーを書く代わりに、標準的なDataverseセキュリティロールでアクセスを管理します。これは内部ユーザーで使われる役割、権限、管理ツールと同じです。このモデルは現在プレビュー段階にあり、Microsoftの機能とPower Portals Proのサポートの両方が対象であり、Power Portals ProはMicrosoftのリリーススケジュールに従って一般提供される予定です。

有効化されると、PowerPortalsProは各ポータル連絡先に対してシステム管理(C2)systemuserを自動的にプロビジョニングします。新規連絡先の登録時と、既存連絡先のサインイン時に遅く対応する際の対応で、連絡先、システムユーザー、Power Pagesサイトをリンクするpowerpagesusermappingレコードも含まれます。セッションのDataverseコールはすべてそのシステムユーザーになりすまし、Power Pagesがあなたのウェブロールとテーブル権限から同期するセキュリティロールが、ユーザーが何を見たり何をしたりできるかを正確に管理します。セッションには多くのContactStubUserPortalUserTypeされるため、UIはプロビジョニング済みユーザーと実際の内部ユーザーを常に区別できます。

注記

このセキュリティモデルを使うには、Dataverse環境内でPower Pagesのウェブサイトを作成する必要があります。これがMicrosoft Frameworkコンポーネントをインストールし、統一セキュリティ機能を有効にするためのものです。有料のPower Pagesプランは不要で、機能のインストールと有効化後はすぐにウェブサイト自体を削除できます。PowerPagesSiteIdが参照するPower Pagesのサイトレコード(powerpagesite)は環境内に存在している必要があります。なぜなら、ユーザーマッピングやセキュリティロール同期がそれに対してリゾリュートするからです。

Dataverseネイティブセキュリティの実現

サーバーのProgram.csSecurityOptionsを有効にし、Power PagesのサイトアカウントのIDを入力してください:

構成はアプリケーション起動時に検証されます。 ProvisionSystemUsers が有効になったら、 PowerPagesSiteId を設定し、既存の powerpagesite レコードに解決しなければならず、そうでなければアプリケーションはガイダンスから起動できません。

Power Pagesと同じようにアクセス権を付与してください:Power Pages管理アプリで ウェブロールテーブル権限 を設定し、連絡先にウェブロールを割り当てる(管理アプリを通じてまたはプログラムで)。プラットフォームはそれらを自動生成されるセキュリティロール( PowerPages_*と名付けられた)に同期し、ウェブロールのメンバーシップ変更時に自動的に割り当てます。設定は完全にPower Pages上で行われているため、ポータルは実際のPower Pagesサイトとスムーズに移動できます。役割や権限の変更は、Dataverseのキャッシュ内で伝播するまでに数秒から数分かかることがあることに注意してください。

ステップバイステップのセットアップガイドに従ってください

はじめに

1. 権限ハンドラーを作成する

ITablePermissionHandlerITableRecordPermissionHandlerを実装するクラスを作成しましょう。Tableプロパティをハンドラが適用するDataverseテーブルの論理名に設定し、各権限メソッドを実装します。

以下は、特定のテーブルに対してすべてのユーザーに完全なアクセス権を与える簡単な例です:

2. 依存注入におけるレジスタ

プロジェクトの Program.cs ファイル内のDIコンテナ(またはサービス収集拡張メソッド)にハンドラーを登録してください:

ハンドラーはDIコンテナから解決されるため、必要なサービス(データベースコンテキストやユーザーサービスなど)をインジェクション(コンストラクタインジェクション)で注入できます。

記録レベルのセキュリティ

アクセスが操作される特定のレコードに依存するシナリオでは、ITableRecordPermissionHandlerを実装してください。このインターフェースはTableRecordを受信する過負荷を拡張してITablePermissionHandlerします。

以下の例では、すべてのユーザーがレコードをグローバルに読み取れるようにしますが、書き込み操作は現在のユーザーが所有するレコードに限定しています。

注記

CanUpdateAsyncレコードレベルのオーバーロードは、提案された更新情報(recordWithUpdates)と現在永続化状態(currentRecord)のレコードの両方を提供し、値を比較したり特定のフィールド変更を検証したりすることを可能にします。

必須欄

RequiredColumnsプロパティは、ハンドラーがレコードレベルの権限を評価するためにどの列を取得する必要があるかを指定します。フレームワークは、これらの列がまだ含まれていない場合、自動的にFetchXMLクエリに追加し、ビューやクエリにこれらの列が含まれていなくても、ハンドラーが常に必要なデータを保持できるようにします。

以下の例では、 ppp_owningportaluserid ルックアップ列を使って、現在のユーザーが所有するレコードへのアクセスを制限しています。

注記

RequiredColumnsが空のリストを返し、ハンドラーのレコードレベルのメソッドがrecord.Idのみを使用する場合、クエリに追加の列は追加されません。ownerプロパティは、RequiredColumnsに関係なく常にプラットフォームから提供されます。

fetchXMLクエリフィルタインターセプタ

テーブルレベルやレコードレベルのセキュリティに加え、PowerPortalsProは IFetchXmlQueryFilterInterceptor をサポートしています。これは、FetchXMLクエリを実行前に修正できるインターフェースです。これは、ユーザーが自分やチームの記録のみを見られるようにするなど、行レベルのフィルタリングを強制するのに役立ちます。

IFetchXmlQueryFilterInterceptorITablePermissionHandlerを拡張するため、各インターセプタはTableプロパティと標準パーミッションメソッドを通じてテーブルレベルの権限も定義します。インターセプタのOnQueryAsyncメソッドは、指定されたテーブルを対象としたクエリに対してのみ呼び出されます。

レコードレベルの権限ハンドラが各レコードを取得し た後 に評価するのとは異なり、クエリフィルターインターセプターはクエリがDataverseに到達 する前に クエリを修正します。フィルタアウトされたレコードは一度も取得されないため、パフォーマンスとセキュリティが向上し、さらに重要なのは、検索後にフィルタリングをかけるとページ数が短くなり、合計数が誤ってカウントされるため、グリッドページや総カウントの精度を保つことができます。

1. クエリフィルターインターセプタの作成

IFetchXmlQueryFilterInterceptorを実装し、Tableプロパティをテーブルの論理名に設定し、権限メソッドを実装し、OnQueryAsyncFetchXMLBuilderを使ってクエリにフィルターを追加します。FetchXmlParametersレコードは現在のユーザーのEntityReferenceを提供します。 FetchXMLBuilder

以下の例は、 contact テーブルへのクエリを現在のユーザーと一致するレコードのみを返すように制限しています。

2. 依存注入におけるレジスタ

インターセプターを IFetchXmlQueryFilterInterceptorITablePermissionHandler の両方として登録し、クエリフィルタリングとテーブルレベルの権限の両方を適用してください。複数のインターセプターを登録でき、それぞれがテーブルを対象としたクエリに対して実行されます。

ヒント

IFetchXmlQueryFilterInterceptorITablePermissionHandlerを拡張するため、単一のクラスでテーブルレベルの権限とクエリレベルのフィルタリングの両方を処理します。OnQueryAsyncメソッドはインターセプタのTableプロパティに一致するクエリにのみ呼び出されるため、メソッド内のテーブル名を確認する必要はありません。

組み込みの基本クラス

このフレームワークは、一般的なセキュリティパターンを簡素化するための基本クラスを提供します:

API参照

ITablePermissionHandler Interface

性質

名称
種類
デフォルト
概要
Tablestring
この権限ハンドラーが適用されるテーブルの論理名。
名称: Table
種類: string
概要: この権限ハンドラーが適用されるテーブルの論理名。

方法

名称
パラメータ
種類
概要
CanAppendAsyncGuid? userId
Task<bool>
ユーザーがレコードを追加できるかどうかを判断する方法。
CanAppendToAsyncGuid? userId
Task<bool>
ユーザーがレコードに付加できるかどうかを判断する方法。
CanCreateAsyncGuid? userId
Task<bool>
ユーザーがレコードを作成できるかどうかを判断する方法。
CanDeleteAsyncGuid? userId
Task<bool>
ユーザーがレコードを削除できるかどうかを判断する方法。
CanReadAsyncGuid? userId
Task<bool>
ユーザーがレコードを読み取れるかどうかを判断する方法。
CanUpdateAsyncGuid? userId
Task<bool>
ユーザーがレコードを更新できるかどうかを判断する方法。
名称: CanAppendAsync
パラメータ: Guid? userId
種類: Task<bool>
概要: ユーザーがレコードを追加できるかどうかを判断する方法。
名称: CanAppendToAsync
パラメータ: Guid? userId
種類: Task<bool>
概要: ユーザーがレコードに付加できるかどうかを判断する方法。
名称: CanCreateAsync
パラメータ: Guid? userId
種類: Task<bool>
概要: ユーザーがレコードを作成できるかどうかを判断する方法。
名称: CanDeleteAsync
パラメータ: Guid? userId
種類: Task<bool>
概要: ユーザーがレコードを削除できるかどうかを判断する方法。
名称: CanReadAsync
パラメータ: Guid? userId
種類: Task<bool>
概要: ユーザーがレコードを読み取れるかどうかを判断する方法。
名称: CanUpdateAsync
パラメータ: Guid? userId
種類: Task<bool>
概要: ユーザーがレコードを更新できるかどうかを判断する方法。

ITableRecordPermissionHandler Interface

性質

名称
種類
デフォルト
概要
RequiredColumnsList<string>
このハンドラがレコードレベルの権限を評価するために取得しなければならない列の論理名の一覧。
Tablestring
この権限ハンドラーが適用されるテーブルの論理名。
名称: RequiredColumns
種類: List<string>
概要: このハンドラがレコードレベルの権限を評価するために取得しなければならない列の論理名の一覧。
名称: Table
種類: string
概要: この権限ハンドラーが適用されるテーブルの論理名。

方法

名称
パラメータ
種類
概要
CanAppendAsyncGuid? userId
TableRecord record
Task<bool>
ユーザーが提供されたレコードを付加できるかどうかを判断する方法。
CanAppendToAsyncGuid? userId
TableRecord record
Task<bool>
ユーザーが提供されたレコードに付加可能かどうかを判断する方法。
CanCreateAsyncGuid? userId
TableRecord record
Task<bool>
ユーザーが提供されたレコードを作成できるかどうかを判断する方法。
CanDeleteAsyncGuid? userId
TableRecord record
Task<bool>
ユーザーが提供されたレコードを削除できるかどうかを判断する方法。
CanReadAsyncGuid? userId
TableRecord record
Task<bool>
ユーザーが提供されたレコードを読めるかどうかを判断する方法。
CanUpdateAsyncGuid? userId
TableRecord recordWithUpdates
TableRecord currentRecord
Task<bool>
ユーザーが提供されたレコードを更新できるかどうかを判断する方法。
名称: CanAppendAsync
パラメータ: Guid? userId
TableRecord record
種類: Task<bool>
概要: ユーザーが提供されたレコードを付加できるかどうかを判断する方法。
名称: CanAppendToAsync
パラメータ: Guid? userId
TableRecord record
種類: Task<bool>
概要: ユーザーが提供されたレコードに付加可能かどうかを判断する方法。
名称: CanCreateAsync
パラメータ: Guid? userId
TableRecord record
種類: Task<bool>
概要: ユーザーが提供されたレコードを作成できるかどうかを判断する方法。
名称: CanDeleteAsync
パラメータ: Guid? userId
TableRecord record
種類: Task<bool>
概要: ユーザーが提供されたレコードを削除できるかどうかを判断する方法。
名称: CanReadAsync
パラメータ: Guid? userId
TableRecord record
種類: Task<bool>
概要: ユーザーが提供されたレコードを読めるかどうかを判断する方法。
名称: CanUpdateAsync
パラメータ: Guid? userId
TableRecord recordWithUpdates
TableRecord currentRecord
種類: Task<bool>
概要: ユーザーが提供されたレコードを更新できるかどうかを判断する方法。

IFetchXmlQueryFilterInterceptor Interface

性質

名称
種類
デフォルト
概要
Tablestring
この権限ハンドラーが適用されるテーブルの論理名。
名称: Table
種類: string
概要: この権限ハンドラーが適用されるテーブルの論理名。

方法

名称
パラメータ
種類
概要
CanAppendAsyncGuid? userId
Task<bool>
ユーザーがレコードを追加できるかどうかを判断する方法。
CanAppendToAsyncGuid? userId
Task<bool>
ユーザーがレコードに付加できるかどうかを判断する方法。
CanCreateAsyncGuid? userId
Task<bool>
ユーザーがレコードを作成できるかどうかを判断する方法。
CanDeleteAsyncGuid? userId
Task<bool>
ユーザーがレコードを削除できるかどうかを判断する方法。
CanReadAsyncGuid? userId
Task<bool>
ユーザーがレコードを読み取れるかどうかを判断する方法。
CanUpdateAsyncGuid? userId
Task<bool>
ユーザーがレコードを更新できるかどうかを判断する方法。
OnQueryAsyncFetchXMLBuilder fetchXmlBuilder
FetchXmlParameters parameters
Task<FetchXMLBuilder>
FetchXMLクエリを実行前に修正するために呼び出されます。
名称: CanAppendAsync
パラメータ: Guid? userId
種類: Task<bool>
概要: ユーザーがレコードを追加できるかどうかを判断する方法。
名称: CanAppendToAsync
パラメータ: Guid? userId
種類: Task<bool>
概要: ユーザーがレコードに付加できるかどうかを判断する方法。
名称: CanCreateAsync
パラメータ: Guid? userId
種類: Task<bool>
概要: ユーザーがレコードを作成できるかどうかを判断する方法。
名称: CanDeleteAsync
パラメータ: Guid? userId
種類: Task<bool>
概要: ユーザーがレコードを削除できるかどうかを判断する方法。
名称: CanReadAsync
パラメータ: Guid? userId
種類: Task<bool>
概要: ユーザーがレコードを読み取れるかどうかを判断する方法。
名称: CanUpdateAsync
パラメータ: Guid? userId
種類: Task<bool>
概要: ユーザーがレコードを更新できるかどうかを判断する方法。
名称: OnQueryAsync
パラメータ: FetchXMLBuilder fetchXmlBuilder
FetchXmlParameters parameters
種類: Task<FetchXMLBuilder>
概要: FetchXMLクエリを実行前に修正するために呼び出されます。