Procédure : créer un gestionnaire d’autorisations personnalisé pour un service

L’infrastructure de modèle d’identité dans Windows Communication Foundation (WCF) prend en charge un modèle d’autorisation extensible basé sur des revendications. Les revendications sont extraites de jetons et sont éventuellement traitées par les stratégies d'autorisation personnalisées puis placées dans un AuthorizationContext. Un gestionnaire d'autorisations examine les revendications dans le AuthorizationContext pour prendre des décisions concernant les autorisations.

Par défaut, les décisions relatives aux autorisations sont prises par la classe ServiceAuthorizationManager ; cependant, ces décisions peuvent être substituées en créant un gestionnaire d'autorisations personnalisé. Pour créer un gestionnaire d'autorisations personnalisé, créez une classe qui dérive de ServiceAuthorizationManager et implémente la méthode CheckAccessCore. Les décisions relatives aux autorisations sont prises dans la méthode CheckAccessCore, qui retourne la valeur true lorsque l'accès est accordé et false lorsque l'accès est refusé.

Si la décision d'autorisation dépend du contenu du corps de message, utilisez la méthode CheckAccess.

En raison des problèmes de performances, essayez de reconcevoir si possible votre application afin que la décision d'autorisation ne nécessite pas l'accès au corps du message.

L'enregistrement du gestionnaire d'autorisations personnalisé pour un service peut être réalisé dans du code ou dans la configuration.

Pour créer un gestionnaire d'autorisations personnalisé

  1. Dérivez une classe d'une classe de la classe ServiceAuthorizationManager.

    public class MyServiceAuthorizationManager : ServiceAuthorizationManager
    {
    
    
    Public Class MyServiceAuthorizationManager
        Inherits ServiceAuthorizationManager
    
    
  2. Remplacez la méthode CheckAccessCore(OperationContext) .

    Utilisez le OperationContext passé à la méthode CheckAccessCore(OperationContext) pour prendre des décisions concernant les autorisations.

    L'exemple de code suivant utilise la méthode FindClaims(String, String) pour rechercher la revendication personnalisée http://www.contoso.com/claims/allowedoperation afin de prendre une décision relative à une autorisation.

    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
    

Pour enregistrer un gestionnaire d'autorisations personnalisé à l'aide de code

  1. Créez une instance du gestionnaire d'autorisations personnalisé et assignez-la à la propriété ServiceAuthorizationManager.

    ServiceAuthorizationBehavior est accessible à l'aide de la propriété Authorization.

    L'exemple de code suivant enregistre le gestionnaire d'autorisations personnalisé 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()
    
    

Pour enregistrer un gestionnaire d'autorisations personnalisé à l'aide d'une configuration

  1. Ouvrez le fichier de configuration pour le service.

  2. Ajoutez un élément <serviceAuthorization> à l’élément <behaviors>.

    Pour l’élément <serviceAuthorization>, ajoutez un attribut serviceAuthorizationManagerType et affectez-lui le type qui représente le gestionnaire d’autorisations personnalisé.

  3. Ajoutez une liaison qui sécurise la communication entre le client et le service.

    La liaison choisie pour cette communication détermine les revendications ajoutées au AuthorizationContext, que le gestionnaire d'autorisations personnalisé utilise pour prendre des décisions concernant les autorisations. Pour plus d’informations sur les liaisons fournies par le système, consultez Liaisons fournies par le système.

  4. Associez le comportement à un point de terminaison de service, en ajoutant un élément <service> et en affectant à l’attribut behaviorConfiguration la valeur de l’attribut de nom de l’élément <behavior>.

    Pour plus d’informations sur la configuration d’un point de terminaison de service, consultez Guide pratique pour créer un point de terminaison de service dans la configuration.

    L'exemple de code suivant enregistre le gestionnaire d'autorisations personnalisé 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>
    

    Avertissement

    Notez que lorsque vous spécifiez serviceAuthorizationManagerType, la chaîne doit contenir le nom de type qualifié complet. une virgule, et le nom de l'assembly dans lequel le type est défini. Si vous omettez le nom de l'assembly, WCF tentera de charger le type à partir de System.ServiceModel.dll.

Exemple

L'exemple de code suivant illustre une implémentation de base d'une classe ServiceAuthorizationManager qui inclut la substitution de la méthode CheckAccessCore. L'exemple de code recherche une revendication personnalisée dans le AuthorizationContext et retourne la valeur true lorsque la ressource pour cette revendication personnalisée correspond à la valeur d'action du OperationContext. Pour obtenir une implémentation plus complète d’une classe ServiceAuthorizationManager, consultez Stratégie d’autorisation.

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

Voir aussi