Procedimiento para crear un administrador de autorización personalizado para un servicio

En la infraestructura del modelo de identidad de Windows Communication Foundation (WCF), se admite el uso de un modelo de autorización extensible basado en demandas. Las demandas se extraen de los tokens y opcionalmente son procesadas por directivas de autorización personalizadas y, a continuación, colocadas en AuthorizationContext. Un administrador de autorización examina las demandas en AuthorizationContext para tomar las decisiones de autorización.

La clase ServiceAuthorizationManager toma de forma predeterminada, las decisiones de la autorización; sin embargo estas decisiones se pueden invalidar creando un administrador de autorización personalizado. Para crear un administrador de autorización personalizado, cree una clase que derive de ServiceAuthorizationManager e implemente el método CheckAccessCore. Las decisiones de la autorización se toman en el método CheckAccessCore, que devuelve true cuando se permite el acceso y false cuando se niega el acceso.

Si la decisión de autorización depende del contenido del cuerpo del mensaje, utilice el método CheckAccess.

Debido a los problemas de rendimiento, en la medida de lo posible debe rediseñar su aplicación para que la decisión de autorización no requiera el acceso al cuerpo del mensaje.

El registro del administrador de autorización personalizado para un servicio se puede hacer en código o configuración.

Para crear un administrador de autorización personalizado

  1. Derive una clase de la clase ServiceAuthorizationManager.

    public class MyServiceAuthorizationManager : ServiceAuthorizationManager
    {
    
    
    Public Class MyServiceAuthorizationManager
        Inherits ServiceAuthorizationManager
    
    
  2. Invalide el método CheckAccessCore(OperationContext) .

    Utilice el OperationContext que se pasa al método CheckAccessCore(OperationContext) para tomar las decisiones de autorización.

    El siguiente ejemplo de código utiliza el método FindClaims(String, String) para buscar el http://www.contoso.com/claims/allowedoperation de la notificación personalizada y tomar una decisión de autorización.

    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
    

Para registrar a un administrador de autorización personalizado mediante código

  1. Cree una instancia del administrador de autorización personalizado y asígnelo a la propiedad ServiceAuthorizationManager.

    Se puede tener acceso a ServiceAuthorizationBehavior mediante la propiedad Authorization.

    El ejemplo de código siguiente registra el administrador de autorización personalizado 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()
    
    

Para registrar a un administrador de autorización personalizado mediante configuración

  1. Abra el archivo de configuración para el servicio.

  2. Agregue un elemento <serviceAuthorization> en la estructura <behaviors>.

    En el elemento <serviceAuthorization>, agregue un atributo serviceAuthorizationManagerType y establezca su valor en el tipo que se use para representar al administrador de autorización personalizado.

  3. Agregue un enlace que proteja la comunicación entre el cliente y el servicio.

    El enlace que se elige para esta comunicación determina las demandas que se agregan al AuthorizationContext, que el administrador de autorización personalizado utiliza para tomar las decisiones de autorización. Para obtener más detalles sobre los enlaces proporcionados por el sistema, consulte Enlaces proporcionados por el sistema.

  4. Asocie el comportamiento con un punto de conexión de servicio. Para ello, agregue un elemento <service> y establezca el valor del atributo behaviorConfiguration con el valor del atributo de nombre del elemento <behavior>.

    Para obtener más información sobre el proceso de configuración de un punto de conexión de servicio, consulte Procedimiento para crear un punto de conexión de servicio en la configuración.

    El ejemplo de código siguiente registra el administrador de autorización personalizado 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>
    

    Advertencia

    Tenga en cuenta que cuando se especifica el serviceAuthorizationManagerType, la cadena debe contener el nombre de tipo completo. una coma, y el nombre del ensamblado en el que el tipo está definido. Si deja fuera el nombre del ensamblado, WCF intentará cargar el tipo desde System.ServiceModel.dll.

Ejemplo

El ejemplo de código siguiente muestra una implementación básica de una clase ServiceAuthorizationManager que incluye la invalidación del método CheckAccessCore. El código de ejemplo examina AuthorizationContext para una demanda personalizada y devuelve true cuando el recurso para esa demanda de la costumbre coincide con el valor de la acción de OperationContext. Para obtener una implementación más completa de una clase ServiceAuthorizationManager, consulte Directiva de autorización.

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

Consulte también