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 : ServiceAuthorizationManager
    {
    
    
    Public Class MyServiceAuthorizationManager
        Inherits ServiceAuthorizationManager
    
    
  2. Überschreiben Sie die CheckAccessCore(OperationContext) -Methode.

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

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

    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 "http://www.contoso.com/claims/allowedoperation".
            foreach (Claim c in cs.FindClaims("http://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;
    }
    
    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 "http://www.contoso.com/claims/allowedoperation".
                Dim c As Claim
                For Each c In cs.FindClaims("http://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
    

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 dem <Verhalten> eine <ServiceAuthorization>hinzu.

    Fügen Sie dem <serviceAuthorization> 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. Weitere Informationen zu den vom System bereitgestellten Bindungen finden Sie unter Vom System bereitgestellteBindungen.

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

    Weitere Informationen zur Konfiguration eines Dienstendpunkts finden Sie unter Vorgehensweise: Erstellen eines Dienstendpunkts in der 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="http://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,MyAssembly" />
             </behavior>
         </serviceBehaviors>
       </behaviors>
      </system.serviceModel>
    </configuration>
    

    Warnung

    Beachten Sie, dass die Zeichenfolge den vollqualifizierten Typnamen enthalten muss, wenn Sie serviceAuthorizationManagerType angeben. ein Komma und der Name der Assembly, in der der Typ definiert ist. Wenn Sie den Assemblynamen auslassen, versucht WCF, den Typ aus System.ServiceModel.dll zu laden.

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 : 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 "http://www.contoso.com/claims/allowedoperation".
          foreach (Claim c in cs.FindClaims("http://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;
  }
}

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 "http://www.contoso.com/claims/allowedoperation".
                Dim c As Claim
                For Each c In cs.FindClaims("http://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

Siehe auch