Condividi tramite


Procedura: creare un gestore autorizzazioni personalizzato per un servizio

L'infrastruttura del modello di identità in Windows Communication Foundation (WCF) supporta un modello di autorizzazione estendibile basato su attestazioni. Le attestazioni vengono estratte dai token, elaborate facoltativamente da criteri di autorizzazione personalizzati e quindi inserite in una classe AuthorizationContext. Un gestore autorizzazioni esamina le attestazioni contenute nel contesto AuthorizationContext per prendere decisioni di autorizzazione.

Per impostazione predefinita, le decisioni di autorizzazione sono prese dalla classe ServiceAuthorizationManager. È tuttavia possibile creare un gestore autorizzazioni personalizzato per eseguire l'override di queste decisioni. Per creare un gestore autorizzazioni personalizzato, creare una classe che deriva da ServiceAuthorizationManager e che implementa il metodo CheckAccessCore. Le decisioni di autorizzazione sono prese tramite il metodo CheckAccessCore che restituisce true quando l'accesso è concesso e false quando l'accesso è negato.

Se la decisione di autorizzazione dipende dal contenuto del corpo del messaggio, utilizzare il metodo CheckAccess.

A causa di problemi riguardanti le prestazioni, è consigliabile ridisegnare l'applicazione, se possibile, in modo tale che per la decisione di autorizzazione non sia necessario l'accesso al corpo del messaggio.

La registrazione del gestore autorizzazioni personalizzato per un servizio può essere eseguita in codice o in configurazione.

Per creare un gestore autorizzazioni personalizzato

  1. Derivare una classe dalla classe ServiceAuthorizationManager.

    public class MyServiceAuthorizationManager : ServiceAuthorizationManager
    {
    
    
    Public Class MyServiceAuthorizationManager
        Inherits ServiceAuthorizationManager
    
    
  2. Eseguire l'override del metodo CheckAccessCore(OperationContext).

    Utilizzare il contesto OperationContext passato al metodo CheckAccessCore(OperationContext) per prendere decisioni di autorizzazione.

    Nell'esempio di codice seguente il metodo FindClaims(String, String) viene utilizzato per individuare l'attestazione personalizzata http://www.contoso.com/claims/allowedoperation allo scopo di prendere una decisione di autorizzazione.

    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
    

Per registrare un gestore autorizzazioni personalizzato in codice

  1. Creare un'istanza del gestore autorizzazioni personalizzato e assegnarla alla proprietà ServiceAuthorizationManager.

    Per accedere al comportamento ServiceAuthorizationBehavior è possibile utilizzare la proprietà Authorization.

    Nell'esempio di codice seguente viene illustrato come registrare il gestore autorizzazioni personalizzato MyServiceAuthorizationManager.

    // 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()
    
    

Per registrare un gestore autorizzazioni personalizzato in configurazione

  1. Aprire il file di configurazione del servizio.

  2. Aggiungere un elemento <serviceAuthorization> all'elemento <behaviors>.

    Per <serviceAuthorization>, aggiungere un attributo serviceAuthorizationManagerType e impostarne il valore sul tipo che rappresenta la gestione autorizzazioni personalizzata.

  3. Aggiungere un'associazione in grado di proteggere la comunicazione tra client e servizio.

    L'associazione scelta per questa comunicazione determina le attestazioni aggiunte al contesto AuthorizationContext utilizzate dal gestore autorizzazioni personalizzato per prendere le decisioni di autorizzazione. Per altre informazioni sui binding forniti dal sistema, vedere Binding forniti dal sistema.

  4. Associare il comportamento a un endpoint del servizio aggiungendo un elemento <service> e impostando il valore dell'attributo behaviorConfiguration sul valore dell'attributo name per l'elemento <behavior>.

    Per altre informazioni sulla configurazione di un endpoint di servizio, vedere Procedura: Creare un endpoint di servizio in Configuration.

    Nell'esempio di codice seguente viene illustrato come registrare il gestore autorizzazioni personalizzato Samples.MyServiceAuthorizationManager.

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

    Avviso

    Si noti che quando si specifica l'oggetto serviceAuthorizationManagerType, la stringa deve contenere il nome di tipo completo, una virgola e il nome dell'assembly in cui il tipo è definito. Se si omette il nome dell'assembly, WCF tenterà di caricare il tipo da System.ServiceModel.dll.

Esempio

Nell'esempio di codice seguente viene descritta un'implementazione di base di una classe ServiceAuthorizationManager che prevede l'override del metodo CheckAccessCore. Nell'esempio di codice viene eseguita una ricerca all'interno del contesto AuthorizationContext allo scopo di individuare un'attestazione personalizzata e quindi viene restituito true quando la risorsa relativa a tale attestazione personalizzata corrisponde al valore di azione indicato nel contesto OperationContext. Per un'implementazione più completa di una classe ServiceAuthorizationManager, vedere Criteri di autorizzazione.

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

Vedi anche