Zugriff im Code verifizieren

Die einzige Zeit, in der Sie sich keine Gedanken über Sicherheitskonzepte machen müssen, ist, wenn Sie Code schreiben, der von einem Benutzer mit der Sicherheitsrolle „Systemadministrator“ ausgeführt wird. Da diese Rolle sehr mächtig ist und nicht bearbeitet werden kann, können Sie sicher sein, dass der Benutzer alles tun kann. In allen anderen Fällen müssen Sie berücksichtigen, wie die Sicherheit angewendet wird.

  • Wenn Sie eine Client-Anwendung erstellen, sollten Sie die Berechtigungen des Benutzers für eine Tabelle oder einen bestimmten Tabellendatensatz auswerten und steuern, welche Befehle Sie aktivieren. Wenn ein Benutzer nicht berechtigt ist, eine Tabelle zu erstellen, können Sie die Benutzeroberfläche in Ihrer App deaktivieren, um das Erstellen einer neuen Tabelle dieses Typs zuzulassen. Wenn sie keinen Lesezugriff auf eine Tabelle haben, kann Ihre Client-Anwendung wählen, keine Komponenten anzuzeigen, die sich auf die Anzeige von Listen dieses Tabellentyps beziehen.

  • Wenn Sie ein synchrones Plug-In schreiben, können Sie nicht irgendeine Datenoperation versuchen und die Ausnahme wegwerfen. Jede Operation, die innerhalb eines synchronen Plug-Ins fehlschlägt, führt dazu, dass für die gesamte Datentransaktion ein Rollback ausgeführt wird. Wenn Sie einen Teil des Prozesses haben, der je nach den Berechtigungen des Benutzers optional ist, sollten Sie zuerst die Berechtigungen des Benutzers überprüfen.

Es gibt zwei Strategien, die Sie anwenden können, um zu erkennen, welche Operationen ein Benutzer durchführen kann:

  • Testen einzelner Tabellendatensätze
  • Prüfen der Sicherheitsrechte des Benutzers

Diese Strategien werden im Folgenden beschrieben.

Testen einzelner Tabellendatensätze

Die Benutzerinteraktion mit bestimmten Tabellendatensätzen beginnt normalerweise mit einer Abfrage. Wenn ein Benutzer keinen Zugriff auf Datensätze für diese Tabelle hat, gibt die Abfrage keine Datensätze zurück und es gibt nichts weiter, was der Benutzer versuchen kann, außer einen neuen Datensatz zu erstellen. Um zu testen, ob der Benutzer einen neuen Datensatz erstellen kann, müssen Sie die andere Strategie (siehe oben) verwenden, um die Sicherheitsberechtigungen des Benutzers zu überprüfen.

Wenn der Benutzer jedoch erfolgreich Datensätze der Tabelle über eine Abfrage abrufen konnte, können Sie anschließend einen Datensatz mit der Nachricht RetrievePrincipalAccess testen.

Die folgende statische Methode GetAccessRights verwendet das SDK RetrievePrincipalAccessRequest-Klasse, um eine Reihe von Zugriffsrechten abzurufen, die ein Benutzer, ein Team oder eine Organisation für einen Datensatz hat, unter Verwendung der AccessRights-Enumeration.

/// <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;
}

Mit dem von dieser Methode zurückgegebenen Wert können Sie die Enum.HasFlag-Methode verwenden, um einen booleschen Wert zurückzugeben, wenn der Benutzer Zugriff hat, um bestimmte Operationen an der Tabelle durchzuführen.

Der folgende Codeausschnitt zeigt, wie Sie die statische Methode GetAccessRights verwenden, um zu testen, ob ein Benutzer Zugriff auf das Anhängen von Datensätzen an einen Kontodatensatz unter Verwendung des Mitglieds AppendToAccess hat.

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);

Bei Zugriff auf einen Datensatz der Tabelle können Sie die zurückgegebenen Zugriffsrechte verwenden, um alle Operationen zu testen, die für diesen Datensatz gelten. Dieser Test umfasst jedoch keine Funktionalitäten, die sich auf andere Operationen beziehen, z. B. das Erstellen eines neuen Datensatzes oder andere Berechtigungen, die nicht an eine bestimmte Tabelle gebunden sind. Für diese Vorgänge müssen Sie die Sicherheitsberechtigungen eines Benutzers überprüfen.

Prinzipale mit Zugriff auf einen Datensatz abrufen

Einige Datenoperationen erfordern, dass ein anderer Benutzer Zugriff auf einen Datensatz hat. Wenn Sie nur einen bestimmten Benutzer, ein bestimmtes Team oder eine bestimmte Organisation haben, können Sie mit der RetrievePrincipalAccess-Nachricht testen.

Wenn Sie jedoch eine Liste aller Benutzer, Teams oder Organisationen benötigen, für die ein Datensatz freigegeben wurde, verwenden Sie die RetrieveSharedPrincipalsAndAccess-Nachricht. RetrieveSharedPrincipalsAndAccess bietet Details zu den Zugriffsrechten, die jeder Benutzer, jedes Team oder jede Organisation hat, weil der Datensatz mit ihnen geteilt wurde.

Die folgende statische Methode GetSharedPrincipalsAndAccess verwendet die RetrieveSharedPrincipalsAndAccessRequest- und RetrieveSharedPrincipalsAndAccessResponse-Klassen, um ein Array von PrincipalAccess-Daten zurückzugeben mit Details zu den Prinzipalen und dem Zugriff, den sie haben, weil der Datensatz mit ihnen geteilt wurde.

/// <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;
}

Überprüfen der Sicherheitsberechtigungen eines Benutzers

Wenn Sie keinen bestimmten Tabellendatensatz zum Testen haben, z. B. ob ein Benutzer einen neuen Tabellendatensatz erstellen kann, müssen Sie sich auf die Überprüfung der Sicherheitsrechte des Benutzers verlassen. Diese Berechtigungen sind in der Berechtigungstabelle gespeichert.

Es gibt fast 1.000 einzelne Rechte in der Dataverse-Datenbank und die Anzahl wächst mit jeder Tabelle, die dem System hinzugefügt wird. Sie können eine Liste der in Ihrer Umgebung verfügbaren Berechtigungen abrufen, indem Sie die folgende FetchXML-Abfrage ausführen.

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

Tipp

Die XrmToolBox FetchXML Builder ist ein nützliches Tool, um FetchXML-Abfragen zu verfassen und zu testen.

Der Wert des Attributs name folgt diesem Muster der Namenskonvention, wenn sich das Privileg auf Tabellen bezieht: „prv+Verb+Tabelle SchemaName“. Das Verb ist eines von Append, AppendTo, Assign, Create, Delete, Share, Write.

Zusätzlich zu den Privilegien für Tabellen gibt es weniger als 100 weitere spezielle Rechte, die nicht mit Tabellen verbunden sind. Sie können die folgende Abfrage verwenden, um diese Rechte abzurufen.

<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>

Verwenden Sie diese Anweisungen, um Berechtigungen nach Berechtigungs-ID oder Name abzurufen. Dazu gehören auch Rechte, die der Benutzer von Teams haben könnte.

Nachricht Web-API-Funktion
SDK-Anforderungsklasse
RetrieveUserPrivilegeByPrivilegeId RetrieveUserPrivilegeByPrivilegeId-Funktion
RetrieveUserPrivilegeByPrivilegeIdRequest-Klasse
RetrieveUserPrivilegeByPrivilegeName RetrieveUserPrivilegeByPrivilegeName-Funktion
RetrieveUserPrivilegeByPrivilegeNameRequest-Klasse
RetrieveUserSetOfPrivilegesByIds RetrieveUserSetOfPrivilegesByIds-Funktion
RetrieveUserSetOfPrivilegesByIdsRequest-Klasse
RetrieveUserSetOfPrivilegesByNames RetrieveUserSetOfPrivilegesByNames-Funktion
RetrieveUserSetOfPrivilegesByNamesRequest-Klasse

Beispiel: Prüfen, ob ein Benutzer eine Berechtigung hat

Die folgenden Beispiele zeigen die Verwendung der RetrieveUserPrivilegeByPrivilegeName Nachricht. Diese Nachricht ruft die Liste der Berechtigungen für einen Systembenutzer (Benutzer) aus allen direkten Rollen ab, die dem Systembenutzer zugeordnet sind, und aus allen indirekten Rollen, die Teams zugeordnet sind, in denen der Systembenutzer basierend auf dem angegebenen Berechtigungsnamen Mitglied ist.

Die folgende statische Methode HasPrivilege gibt zurück, ob der Benutzer über die benannte Berechtigung verfügt.

/// <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;
}

Weitere Informationen:

Abrufen der Rechte für eine Sicherheitsrolle

Sie können die mit einer Sicherheitsrolle verbundenen Berechtigungen abrufen.

Die folgende statische Methode GetRolePrivileges ruft die einer Rolle zugeordneten Berechtigungen ab.

/// <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];
}

Weitere Informationen: Abrufen mit Bezugszeilen

Siehe auch

Plug-Ins

Hinweis

Können Sie uns Ihre Präferenzen für die Dokumentationssprache mitteilen? Nehmen Sie an einer kurzen Umfrage teil. (Beachten Sie, dass diese Umfrage auf Englisch ist.)

Die Umfrage dauert etwa sieben Minuten. Es werden keine personenbezogenen Daten erhoben. (Datenschutzbestimmungen).