Comment : créer un gestionnaire d'autorisations personnalisé pour un service

L'infrastructure Modèle d'identité de 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
        Inherits ServiceAuthorizationManager
    
    
    public class MyServiceAuthorizationManager : ServiceAuthorizationManager
    {
    
  2. Substituez la méthode CheckAccessCore.

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

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

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

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 serviceAuthorization element au Behaviors element.

    Ajoutez un attribut serviceAuthorizationManagerType à serviceAuthorization element 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> of <serviceBehaviors>.

    Pour plus d'informations sur la configuration d'un point de terminaison de service, consultez Comment : 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="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>
    

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 une implémentation plus complète d'une classe ServiceAuthorizationManager, consultez Authorization Policy.

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

Voir aussi

Tâches

Authorization Policy
Authorization Policy

Référence

ServiceAuthorizationManager