コードでのアクセスの確認

セキュリティに関する心配がない場合は、システム管理者セキュリティ ロールのあるユーザーが実行しているコードを記述しているときだけです。 このロールは非常に強く編集できないため、ユーザーに何をさせても大丈夫です。 他のすべての場合、セキュリティがどのように適用されるかを考慮する必要があります。

  • クライアント アプリケーション を作成している場合、テーブルや特定のテーブル レコードに対するユーザーの権限を評価し、有効にするコマンドを制御する必要があります。 ユーザーがテーブルの作成を許可されていない場合は、アプリのユーザー インターフェイスを無効にして、そのタイプの新しいテーブルの作成を許可できます。 テーブルの読み取りアクセス権がない場合、クライアント アプリケーションは、そのタイプのテーブルのリストの表示に関連するコンポーネントの非表示を選択できます。

  • 同期プラグイン を作成している場合、データ操作を試みて例外を破棄することはできません。 同期プラグイン内で失敗した操作があると、データ トランザクション全体がロールバックされます。 ユーザーの権限に応じたオプションのプロセスの一部がある場合は、最初にユーザーの権限を確認する必要があります。

ユーザーが実行できる操作を検出するために適用できる戦略は 2 つあります。

  • 個々のテーブル レコードをテストする
  • ユーザーのセキュリティ権限を確認する

これらの戦略について以下に詳しく説明します。

個々のテーブル レコードをテストする

特定のテーブル レコードに対するユーザーの操作は、通常、クエリから始まります。 ユーザーがそのテーブルのレコードにアクセスできない場合、クエリはレコードを返さず、新しいレコードを作成する以外にユーザーが試行できることはありません。 ユーザーが新しいレコードを作成できるかどうかをテストするには、他の戦略 (上記) を使用してユーザーのセキュリティ特権を確認する必要があります。

ただし、ユーザーがクエリを使用してテーブル レコードの取得に成功した場合は、RetrievePrincipalAccess メッセージを使用してレコードをテストできます。

次の GetAccessRights 静的メソッドは、SDK RetrievePrincipalAccessRequest クラス を使用して、ユーザー、チーム、または組織が AccessRights 列挙型 を使用してレコードに対して持っているアクセス権のセットを取得します。

/// <summary>
/// Gets which access rights a user, team, or organization has for a specific record.
/// </summary>
/// <param name="service">Authenticated client implementing the IOrganizationService interface</param>
/// <param name="userOrTeamOrOrganization">The user, team, or organization to check</param>
/// <param name="entity">A reference to the entity to check.</param>
/// <returns>The access rights the user can perform.</returns>
static AccessRights GetAccessRights(
        IOrganizationService service,
        EntityReference userOrTeamOrOrganization,
        EntityReference entity)
{
    var request = new RetrievePrincipalAccessRequest()
    {
        Principal = userOrTeamOrOrganization,
        Target = entity
    };

    var response = (RetrievePrincipalAccessResponse)service.Execute(request);

    return response.AccessRights;
}

このメソッドによって返される値を使用すると、ユーザーがテーブルに対して特定の操作を実行するためのアクセス権を持っている場合に、Enum.HasFlag メソッド を使用して ブール値 を返します。

次のコード スニペットは、GetAccessRights 静的メソッドを使用し、AppendToAccess メンバーを使用して、ユーザーが特定のアカウント レコードにレコードを追加するためのアクセス権を持っているかどうかを確認する方法を示しています。

var whoIAm = (WhoAmIResponse)service.Execute(new WhoAmIRequest());

var meRef = new EntityReference("systemuser", whoIAm.UserId);

QueryExpression query = new("account") { 
        ColumnSet = new ColumnSet("accountid"),
        TopCount = 1
};

EntityCollection accounts = service.RetrieveMultiple(query);

EntityReference accountRef = accounts
    .Entities
    .FirstOrDefault()
    .ToEntityReference();

AccessRights rights = GetAccessRights(service, meRef, accountRef);

var canAppendTo = rights.HasFlag(AccessRights.AppendToAccess);

テーブル レコードにアクセスすると、返されたアクセス権を使用して、そのレコードに適用されるすべての操作をテストできます。 ただし、新しいレコードや特定のテーブルにバインドされていないその他の特権の作成など、他の操作に適用される機能は含まれていません。 これらの操作では、ユーザーのセキュリティ権限を確認する 必要があります。

レコードにアクセスできるプリンシパルを取得する

一部のデータ操作では、別のユーザーがレコードにアクセスできる必要があります。 特定のユーザーや組織が 1 つしかない場合は、RetrievePrincipalAccess メッセージを使用してテストできます。

ただし、レコードが共有されているすべてのユーザー、チーム、または組織のリストが必要な場合は、RetrieveSharedPrincipalsAndAccess メッセージを使用します。 ユーザー、チーム、または組織とレコードが共有されているため、RetrieveSharedPrincipalsAndAccess は、それぞれが持つアクセス権の詳細を表示します。

次の GetSharedPrincipalsAndAccess 静的メソッドは、レコードが共有されているため、RetrieveSharedPrincipalsAndAccessRequest クラスと RetrieveSharedPrincipalsAndAccessResponse クラスを使用して、所有するプリンシパルとアクセス権の詳細が含まれた PrincipalAccess データの配列を返します。

/// <summary>
/// Returns details about access principals have because a record was shared with them.
/// </summary>
/// <param name="service">Authenticated client implementing the IOrganizationService interface</param>
/// <param name="target">The record to check</param>
/// <returns>The principal access data for each user, team, or organization</returns>
static PrincipalAccess[] GetSharedPrincipalsAndAccess(
    IOrganizationService service,
    EntityReference target)
{
    var request = new RetrieveSharedPrincipalsAndAccessRequest()
    {
        Target = target
    };

    var response = (RetrieveSharedPrincipalsAndAccessResponse)service.Execute(request);

    return response.PrincipalAccesses;
}

ユーザーのセキュリティ権限を確認する

新しいテーブル レコードを作成できるかどうかなど、テストする特定のテーブル レコードがない場合は、ユーザーのセキュリティ権限の確認する必要があります。 これらの権限は、権限テーブル に保存されます。

Dataverse データベースには、約 1,000 の個別の特権があり、その数は、テーブルがシステムに追加される度に増加します。 次の FetchXML クエリを実行することにより、環境で使用可能な特権のリストを取得できます。

<fetch version='1.0' distinct='true' no-lock='true' >
  <entity name='privilege' >
    <attribute name='name' />
  </entity>
</fetch>

ヒント

XrmToolBox FetchXML ビルダーは、FetchXML クエリを作成およびテストするのに役立つツールです。

特権がテーブルに適用される場合、name 属性の値は、次の名前付け規則のパターンに従います: "prv+Verb+Table SchemaName"。 動詞は AppendAppendToAssignCreateDeleteShareWrite のいずれかです。

テーブルの特権に加えて、テーブルに関連付けられていない他の特別な特権の数は 100 未満です。 次のクエリを使用して権限を取得できます。

<fetch version='1.0' distinct='true' no-lock='true' >

<entity name='privilege' >
  <attribute name='name' />
  <filter>
    <condition attribute='name' operator='not-begin-with' value='prvAppend' />
    <condition attribute='name' operator='not-begin-with' value='prvAssign' />
    <condition attribute='name' operator='not-begin-with' value='prvCreate' />
    <condition attribute='name' operator='not-begin-with' value='prvDelete' />
    <condition attribute='name' operator='not-begin-with' value='prvRead' />
    <condition attribute='name' operator='not-begin-with' value='prvShare' />
    <condition attribute='name' operator='not-begin-with' value='prvWrite' />
  </filter>
</entity>

</fetch>

これらのメッセージを使用して、特権 ID または名前で特権を取得します。 これには、ユーザーがチームから与えられる可能性のある特権が含まれます。

Message Web API 関数
SDK 要求クラス
RetrieveUserPrivilegeByPrivilegeId RetrieveUserPrivilegeByPrivilegeId 関数
RetrieveUserPrivilegeByPrivilegeIdRequest クラス
RetrieveUserPrivilegeByPrivilegeName RetrieveUserPrivilegeByPrivilegeName 関数
RetrieveUserPrivilegeByPrivilegeNameRequest クラス
RetrieveUserSetOfPrivilegesByIds RetrieveUserSetOfPrivilegesByIds 関数
RetrieveUserSetOfPrivilegesByIdsRequest クラス
RetrieveUserSetOfPrivilegesByNames RetrieveUserSetOfPrivilegesByNames 関数
RetrieveUserSetOfPrivilegesByNamesRequest クラス

例: ユーザーが特権を持っているかどうかを確認する

次の例は、RetrieveUserPrivilegeByPrivilegeName メッセージの使用を示します。 このメッセージは、指定された権限名に基づいて、システム ユーザー (ユーザー) に関連付けられたすべての直接ロール、およびシステム ユーザーがメンバーであるチームに関連付けられたすべての間接ロールから、システム ユーザー (ユーザー) の権限のリストを取得します。

次の HasPrivilege 静的メソッドは、ユーザーが指定された権限を持っているかどうかを返します。

/// <summary>
/// Returns whether specified user has a named privilege
/// </summary>
/// <param name="service">The IOrganizationService instance to use.</param>
/// <param name="systemUserId">The Id of the user.</param>
/// <param name="privilegeName">The name of the privilege.</param>
/// <returns></returns>
static bool HasPrivilege(IOrganizationService service,
        Guid systemUserId,
        string privilegeName)
{
    var request = new
        RetrieveUserPrivilegeByPrivilegeNameRequest
    {
        PrivilegeName = privilegeName,
        UserId = systemUserId
    };
    var response =
        (RetrieveUserPrivilegeByPrivilegeNameResponse)service
        .Execute(request);
    if (response.RolePrivileges.Length > 0)
    {
        return true;
    }
    return false;
}

詳細情報:

セキュリティ ロール用の特権を取得する

セキュリティ ロールに関連付けられた権限を取得できます。

次の静的 GetRolePrivileges メソッドは、ロールに関連付けられた権限を取得します。

/// <summary>
/// Retrieves the privileges for a role.
/// </summary>
/// <param name="service">Authenticated client implementing the IOrganizationService interface</param>
/// <param name="roleId">The id of the role</param>
/// <returns>Privilege records associated to the role</returns>
static EntityCollection GetRolePrivileges(IOrganizationService service, Guid roleId) {

    Relationship roleprivileges_association = new("roleprivileges_association");

    var relationshipQueryCollection = new RelationshipQueryCollection();

    var relatedPrivileges = new QueryExpression("privilege")
    {
        ColumnSet = new ColumnSet("name")
    };

    relationshipQueryCollection.Add(roleprivileges_association, relatedPrivileges);

    var request = new RetrieveRequest()
    {
        ColumnSet = new ColumnSet(true),
        RelatedEntitiesQuery = relationshipQueryCollection,
        Target = new EntityReference("role", roleId)
    };

    var response = (RetrieveResponse)service.Execute(request);

    return response.Entity.RelatedEntities[roleprivileges_association];
}

詳細情報: 関連行で取得する

関連情報

プラグイン

注意

ドキュメントの言語設定についてお聞かせください。 簡単な調査を行います。 (この調査は英語です)

この調査には約 7 分かかります。 個人データは収集されません (プライバシー ステートメント)。