Partilhar via


Como: Criar um Gerenciador de Autorização Personalizado para um Serviço

A infraestrutura do Modelo de Identidade no Windows Communication Foundation (WCF) oferece suporte a um modelo de autorização extensível baseado em declarações. As declarações são extraídas de tokens e, opcionalmente, processadas por políticas de autorização personalizadas e, em seguida, colocadas em um AuthorizationContextarquivo . Um gerente de autorização examina as reivindicações no para tomar decisões de AuthorizationContext autorização.

Por padrão, as ServiceAuthorizationManager decisões de autorização são tomadas pela classe, no entanto, essas decisões podem ser substituídas pela criação de um gerenciador de autorização personalizado. Para criar um gerenciador de autorização personalizado, crie uma classe que deriva do ServiceAuthorizationManager método e implemente CheckAccessCore . As decisões de autorização são tomadas no método, que retorna true quando o acesso é concedido e false quando o CheckAccessCore acesso é negado.

Se a decisão de autorização depender do conteúdo do corpo da mensagem, use o CheckAccess método.

Devido a problemas de desempenho, se possível, você deve redesenhar seu aplicativo para que a decisão de autorização não exija acesso ao corpo da mensagem.

O registro do gerenciador de autorização personalizado para um serviço pode ser feito em código ou configuração.

Para criar um gerenciador de autorização personalizado

  1. Derive uma classe da ServiceAuthorizationManager classe.

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

    Use o OperationContext que é passado para o CheckAccessCore(OperationContext) método para tomar decisões de autorização.

    O exemplo de código a seguir usa o FindClaims(String, String) método para localizar a declaração http://www.contoso.com/claims/allowedoperation personalizada para tomar uma decisão de autorização.

    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 um gerenciador de autorização personalizado usando código

  1. Crie uma instância do gerenciador de autorização personalizado e atribua-a à ServiceAuthorizationManager propriedade.

    O ServiceAuthorizationBehavior pode ser acessado usando Authorization propriedade.

    O exemplo de código a seguir registra o MyServiceAuthorizationManager gerenciador de autorização personalizado.

    // 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 um gerenciador de autorização personalizado usando a configuração

  1. Abra o arquivo de configuração do serviço.

  2. Adicione um serviceAuthorization> aos <comportamentos>.<

    Para o <serviceAuthorization>, adicione um serviceAuthorizationManagerType atributo e defina seu valor para o tipo que representa o gerenciador de autorização personalizado.

  3. Adicione uma ligação que proteja a comunicação entre o cliente e o serviço.

    A associação escolhida para esta comunicação determina as declarações que são adicionadas AuthorizationContextao , que o gerenciador de autorização personalizado usa para tomar decisões de autorização. Para obter mais detalhes sobre as ligações fornecidas pelo sistema, consulte Ligações fornecidas pelo sistema.

  4. Associe o comportamento a um ponto de extremidade de serviço, adicionando um elemento de serviço> e defina o behaviorConfiguration valor do atributo como o valor do atributo name para o <elemento behavior>.<

    Para obter mais informações sobre como configurar um ponto de extremidade de serviço, consulte Como criar um ponto de extremidade de serviço na configuração.

    O exemplo de código a seguir registra o gerenciador Samples.MyServiceAuthorizationManagerde autorização personalizado .

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

    Aviso

    Observe que quando você especifica o serviceAuthorizationManagerType, a cadeia de caracteres deve conter o nome do tipo totalmente qualificado. uma vírgula e o nome do assembly no qual o tipo é definido. Se você deixar de fora o nome do assembly, o WCF tentará carregar o tipo de System.ServiceModel.dll.

Exemplo

O exemplo de código a seguir demonstra uma implementação básica de uma ServiceAuthorizationManager classe que inclui substituir o CheckAccessCore método. O código de exemplo examina o AuthorizationContext para uma declaração personalizada e retorna true quando o recurso para essa declaração personalizada corresponde ao valor da ação do OperationContext. Para uma implementação mais completa de uma ServiceAuthorizationManager classe, consulte Política de autorização.

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 também