Vorgehensweise: Erstellen eines benutzerdefinierten Autorisierungs-Managers für einen Dienst

Die Identitätsmodellinfrastruktur in Windows Communication Foundation (WCF) unterstützt ein erweiterbares anspruchsbasiertes Autorisierungsmodell. Ansprüche werden aus Token extrahiert, wahlweise mit benutzerdefinierten Autorisierungsrichtlinien verarbeitet und dann in einem AuthorizationContext platziert. Die Ansprüche im AuthorizationContext werden von einem Autorisierungs-Manager geprüft und als Grundlage für Autorisierungsentscheidungen herangezogen.

Standardmäßig werden Autorisierungsentscheidungen von der ServiceAuthorizationManager-Klasse getroffen. Diese Entscheidungen können jedoch durch die Erstellung eines benutzerdefinierten Autorisierungs-Managers außer Kraft gesetzt werden. Wenn Sie Ihren eigenen Autorisierungs-Manager erstellen möchten, erstellen Sie eine Klasse, die von ServiceAuthorizationManager ableitet, und implementieren die CheckAccessCore-Methode. Autorisierungsentscheidungen werden in der CheckAccessCore-Methode getroffen, von der true zurückgegeben wird, wenn Zugriff gewährt wurde, und false, wenn der Zugriff verweigert wurde.

Wenn die Autorisierungsentscheidung vom Inhalt des Nachrichtentexts abhängt, verwenden Sie die CheckAccess-Methode.

Um Leistungseinbußen zu vermeiden, sollten Sie soweit möglich Ihre Anwendung neu entwerfen, sodass für die Autorisierungsentscheidung kein Zugriff auf den Nachrichtentext erforderlich ist.

Die Registrierung des benutzerdefinierten Autorisierungs-Managers für einen Dienst kann im Code oder in der Konfiguration erfolgen.

So erstellen Sie einen benutzerdefinierten Autorisierungs-Manager

  1. Leiten Sie eine Klasse von der ServiceAuthorizationManager-Klasse ab.

    Public Class MyServiceAuthorizationManager
        Inherits ServiceAuthorizationManager
    
    
    public class MyServiceAuthorizationManager : ServiceAuthorizationManager
    {
    
  2. Überschreiben Sie die CheckAccessCore-Methode.

    Verwenden Sie den an die CheckAccessCore-Methode übergebenen OperationContext, um Autorisierungsentscheidungen zu fällen.

    Im folgenden Codebeispiel wird mit der FindClaims-Methode der benutzerdefinierte Anspruch https://www.contoso.com/claims/allowedoperation gesucht, um eine Autorisierungsentscheidung zu treffen.

    Protected Overrides Function CheckAccessCore(ByVal operationContext As OperationContext) As Boolean 
        ' Extract the action URI from the OperationContext. Match this against the claims.
        ' in the AuthorizationContext.
        Dim action As String = operationContext.RequestContext.RequestMessage.Headers.Action
    
        ' Iterate through the various claimsets in the AuthorizationContext.
        Dim cs As ClaimSet
        For Each cs In  operationContext.ServiceSecurityContext.AuthorizationContext.ClaimSets
            ' Examine only those claim sets issued by System.
            If cs.Issuer Is ClaimSet.System Then
                ' Iterate through claims of type "https://www.contoso.com/claims/allowedoperation".
                Dim c As Claim
                For Each c In  cs.FindClaims("https://www.contoso.com/claims/allowedoperation", _
                     Rights.PossessProperty)
                    ' If the Claim resource matches the action URI then return true to allow access.
                    If action = c.Resource.ToString() Then
                        Return True
                    End If
                Next c
            End If
        Next cs 
        ' If this point is reached, return false to deny access.
        Return False
    
    End Function 
    
    protected override bool CheckAccessCore(OperationContext operationContext)
    {                
      // Extract the action URI from the OperationContext. Match this against the claims
      // in the AuthorizationContext.
      string action = operationContext.RequestContext.RequestMessage.Headers.Action;
    
      // Iterate through the various claim sets in the AuthorizationContext.
      foreach(ClaimSet cs in operationContext.ServiceSecurityContext.AuthorizationContext.ClaimSets)
      {
        // Examine only those claim sets issued by System.
        if (cs.Issuer == ClaimSet.System)
        {
          // Iterate through claims of type "https://www.contoso.com/claims/allowedoperation".
            foreach (Claim c in cs.FindClaims("https://www.contoso.com/claims/allowedoperation", Rights.PossessProperty))
          {
            // If the Claim resource matches the action URI then return true to allow access.
            if (action == c.Resource.ToString())
              return true;
          }
        }
      }
    
      // If this point is reached, return false to deny access.
      return false;                 
    }
    

So registrieren Sie einen benutzerdefinierten Autorisierungs-Manager im Code

  1. Erstellen Sie eine Instanz des benutzerdefinierten Autorisierungs-Managers, und weisen Sie sie der ServiceAuthorizationManager-Eigenschaft zu.

    Auf ServiceAuthorizationBehavior kann mit der Authorization-Eigenschaft zugegriffen werden.

    Im folgenden Codebeispiel wird der benutzerdefinierte MyServiceAuthorizationManager-Autorisierungs-Manager registriert.

    ' Add a custom authorization manager to the service authorization behavior.
    serviceHost.Authorization.ServiceAuthorizationManager = _
        New MyServiceAuthorizationManager()
    
    // Add a custom authorization manager to the service authorization behavior.
    serviceHost.Authorization.ServiceAuthorizationManager = 
               new MyServiceAuthorizationManager();
    

So registrieren Sie einen benutzerdefinierten Autorisierungs-Manager in der Konfiguration

  1. Öffnen Sie die Konfigurationsdatei für den Dienst.

  2. Fügen Sie ein serviceAuthorization element zum Behaviors element hinzu.

    Fügen Sie dem serviceAuthorization element ein serviceAuthorizationManagerType-Attribut hinzu, und legen Sie als Wert für das Attribut den Typ fest, der den benutzerdefinierten Autorisierungs-Manager repräsentiert.

  3. Fügen Sie eine Bindung hinzu, durch die die Kommunikation zwischen Client und Dienst gesichert wird.

    Die für diese Kommunikation gewählte Bindung bestimmt die Ansprüche, die zum AuthorizationContext hinzugefügt werden, der vom benutzerdefinierten Autorisierungs-Manager verwendet wird, um Autorisierungsentscheidungen zu treffen. Ausführliche Informationen zu systemeigenen Bindungen finden Sie unter Vom System bereitgestellte Bindungen.

  4. Ordnen Sie das Verhalten einem Dienstendpunkt zu, indem Sie ein <service>behaviorConfiguration-Element hinzufügen, und legen Sie als Wert des <behavior> of <serviceBehaviors>-Attributs den Wert des Namenattributs für das-Element fest.

    Weitere Informationen zum Konfigurieren eines Dienstendpunkts finden Sie unter Gewusst wie: Erstellen eines Dienstendpunkts in einer Konfiguration.

    Im folgenden Codebeispiel wird der benutzerdefinierte Autorisierungs-Manager Samples.MyServiceAuthorizationManager registriert.

    <configuration>
      <system.serviceModel>
        <services>
          <service 
              name="Microsoft.ServiceModel.Samples.CalculatorService"
              behaviorConfiguration="CalculatorServiceBehavior">
            <host>
              <baseAddresses>
                <add baseAddress="https://localhost:8000/ServiceModelSamples/service"/>
              </baseAddresses>
            </host>
            <endpoint address=""
                      binding="wsHttpBinding_Calculator"
                      contract="Microsoft.ServiceModel.Samples.ICalculator" />
          </service>
        </services>
        <bindings>
          <WSHttpBinding>
           <binding name = "wsHttpBinding_Calculator">
             <security mode="Message">
               <message clientCredentialType="Windows"/>
             </security>
            </binding>
          </WSHttpBinding>
    </bindings>
        <behaviors>
          <serviceBehaviors>
            <behavior name="CalculatorServiceBehavior">
              <serviceAuthorization serviceAuthorizationManagerType="Samples.MyServiceAuthorizationManager" />
            </behaviors>
          </serviceBehaviors>
        </behaviors>
      </system.serviceModel>
    </configuration>
    

Beispiel

Das folgende Codebeispiel zeigt eine grundlegende Implementierung einer ServiceAuthorizationManager-Klasse, bei der auch die CheckAccessCore-Methode außer Kraft gesetzt (überschrieben) wird. Im Beispielcode wird der AuthorizationContext auf einen benutzerspezifischen Anspruch hin überprüft und true zurückgegeben, wenn die Ressource für diesen benutzerspezifischen Anspruch zum Aktionswert aus dem OperationContext passt. Eine umfassendere Implementierung einer ServiceAuthorizationManager-Klasse finden Sie unter Autorisierungsrichtlinie.

Public Class MyServiceAuthorizationManager
    Inherits ServiceAuthorizationManager
    
    Protected Overrides Function CheckAccessCore(ByVal operationContext As OperationContext) As Boolean 
        ' Extract the action URI from the OperationContext. Match this against the claims.
        ' in the AuthorizationContext.
        Dim action As String = operationContext.RequestContext.RequestMessage.Headers.Action
        
        ' Iterate through the various claimsets in the AuthorizationContext.
        Dim cs As ClaimSet
        For Each cs In  operationContext.ServiceSecurityContext.AuthorizationContext.ClaimSets
            ' Examine only those claim sets issued by System.
            If cs.Issuer Is ClaimSet.System Then
                ' Iterate through claims of type "https://www.contoso.com/claims/allowedoperation".
                Dim c As Claim
                For Each c In  cs.FindClaims("https://www.contoso.com/claims/allowedoperation", _
                     Rights.PossessProperty)
                    ' If the Claim resource matches the action URI then return true to allow access.
                    If action = c.Resource.ToString() Then
                        Return True
                    End If
                Next c
            End If
        Next cs 
        ' If this point is reached, return false to deny access.
        Return False
    
    End Function 
End Class 
public class MyServiceAuthorizationManager : ServiceAuthorizationManager
{
  protected override bool CheckAccessCore(OperationContext operationContext)
  {                
    // Extract the action URI from the OperationContext. Match this against the claims
    // in the AuthorizationContext.
    string action = operationContext.RequestContext.RequestMessage.Headers.Action;
    
    // Iterate through the various claim sets in the AuthorizationContext.
    foreach(ClaimSet cs in operationContext.ServiceSecurityContext.AuthorizationContext.ClaimSets)
    {
      // Examine only those claim sets issued by System.
      if (cs.Issuer == ClaimSet.System)
      {
        // Iterate through claims of type "https://www.contoso.com/claims/allowedoperation".
          foreach (Claim c in cs.FindClaims("https://www.contoso.com/claims/allowedoperation", Rights.PossessProperty))
        {
          // If the Claim resource matches the action URI then return true to allow access.
          if (action == c.Resource.ToString())
            return true;
        }
      }
    }
    
    // If this point is reached, return false to deny access.
    return false;                 
  }
}

Siehe auch

Aufgaben

Autorisierungsrichtlinie
Autorisierungsrichtlinie

Verweis

ServiceAuthorizationManager