Noções básicas de nível de proteção

A propriedade ProtectionLevel é encontrada em várias classes diferentes, como nas classes ServiceContractAttribute e OperationContractAttribute. A propriedade controla como parte de (ou toda) uma mensagem é protegida. Este tópico explica o recurso WCF (Windows Communication Foundation) e como ele funciona.

Para obter instruções sobre como definir o nível de proteção, confira Como definir a propriedade ProtectionLevel.

Observação

Só é possível definir níveis de proteção no código, não na configuração.

Noções básicas

Para entender o recurso do nível de proteção, as seguintes instruções básicas se aplicam:

  • Existem três níveis básicos de proteção para qualquer parte de uma mensagem. A propriedade (sempre que ocorrer) é definida como um dos valores de enumeração ProtectionLevel. Em ordem crescente de proteção, eles incluem:

    • None.

    • Sign. A parte protegida é assinada digitalmente. Isso garante a detecção de qualquer violação com a parte da mensagem protegida.

    • EncryptAndSign. A parte da mensagem é criptografada para garantir a confidencialidade antes de ser assinada.

  • Você pode definir requisitos de proteção apenas para dados do aplicativo com esse recurso. Por exemplo, os cabeçalhos WS-Addressing são dados de infraestrutura e, portanto, não são afetados pelo ProtectionLevel.

  • Quando o modo de segurança está definido como Transport, toda a mensagem é protegida pelo mecanismo de transporte. Portanto, definir um nível de proteção separado para diferentes partes de uma mensagem não tem efeito.

  • O ProtectionLevel é uma maneira de o desenvolvedor definir o nível mínimo com o qual uma associação deve estar em conformidade. Quando um serviço é implantado, a associação real especificada na configuração pode ou não dar suporte ao nível mínimo. Por exemplo, por padrão, a classe BasicHttpBinding não fornece segurança (embora possa ser habilitada). Portanto, usá-la com um contrato que tenha qualquer configuração diferente de None fará com que uma exceção seja lançada.

  • Se o serviço exigir que o ProtectionLevel mínimo para todas as mensagens seja Sign, um cliente (talvez criado por uma tecnologia não WCF) poderá criptografar e assinar todas as mensagens (o que é mais do que o mínimo necessário). Nesse caso, o WCF não lançará uma exceção, pois o cliente fez mais do que o mínimo. Observe, no entanto, que os aplicativos WCF (serviços ou clientes) não protegerão excessivamente uma parte da mensagem, se possível, mas cumprirão o nível mínimo. Observe também que, ao usar Transport como o modo de segurança, o transporte pode proteger excessivamente o fluxo de mensagens, porque ele é inerentemente incapaz de proteger em um nível mais granular.

  • Se você definir ProtectionLevel explicitamente como Sign ou EncryptAndSign, deverá usar uma associação com a segurança habilitada ou uma exceção será gerada.

  • Se você selecionar uma associação que habilita a segurança e não definir a propriedade ProtectionLevel em nenhum lugar no contrato, todos os dados do aplicativo serão criptografados e assinados.

  • Se você selecionar uma associação que não tenha a segurança habilitada (por exemplo, a classe BasicHttpBinding tem a segurança desabilitada por padrão) e o ProtectionLevel não estiver definido explicitamente, nenhum dos dados do aplicativo será protegido.

  • Se você estiver usando uma associação que aplique segurança no nível do transporte, todos os dados do aplicativo serão protegidos de acordo com os recursos do transporte.

  • Se você usar uma associação que aplique segurança no nível da mensagem, os dados do aplicativo serão protegidos de acordo com os níveis de proteção definidos no contrato. Se você não especificar um nível de proteção, todos os dados do aplicativo nas mensagens serão criptografados e assinados.

  • O ProtectionLevel pode ser definido em diferentes níveis de escopo. Há uma hierarquia associada ao escopo, que é explicada na próxima seção.

Scoping

Configurar ProtectionLevel na API mais alta define o nível para todos os níveis abaixo dela. Se ProtectionLevel for definido como um valor diferente em um nível inferior, todas as APIs abaixo desse nível na hierarquia serão redefinidas para o novo nível (as APIs acima dela, no entanto, ainda serão afetadas pelo nível superior). A hierarquia é a seguinte. Os atributos no mesmo nível são pares.

Programação de ProtectionLevel

Para programar ProtectionLevel em qualquer ponto da hierarquia, basta definir a propriedade como um valor apropriado ao aplicar o atributo. Para obter exemplos, confira Como: definir a propriedade ProtectionLevel.

Observação

Definir a propriedade em falhas e contratos de mensagem exige a compreensão de como esses recursos funcionam. Para saber mais, confira Como: Definir a propriedade ProtectionLevel e Usar contratos de mensagem.

Dependência de WS-Addressing

Na maioria dos casos, usar a Ferramenta do Utilitário de Metadados do ServiceModel (Svcutil.exe) para gerar um cliente garante que os contratos de cliente e serviço sejam idênticos. No entanto, contratos aparentemente idênticos podem fazer com que o cliente gere uma exceção. Isso ocorre sempre que uma associação não dá suporte à especificação WS-Addressing, e vários níveis de proteção são especificados no contrato. Por exemplo, a classe BasicHttpBinding não dá suporte à especificação, ou você cria uma associação personalizada que não dá suporte a WS-Addressing. O recurso ProtectionLevel depende da especificação WS-Addressing para habilitar níveis diferentes de proteção em um único contrato. Se a associação não der suporte à especificação WS-Addressing, todos os níveis serão definidos no mesmo nível de proteção. O nível de proteção efetivo para todos os escopos no contrato será definido como o nível de proteção mais forte usado no contrato.

Isso pode causar um problema difícil de depurar à primeira vista. É possível criar um contrato de cliente (uma interface) que inclui métodos para mais de um serviço. Ou seja, a mesma interface é usada para criar um cliente que se comunica com muitos serviços, e a interface única contém métodos para todos os serviços. O desenvolvedor deve tomar cuidado nesse cenário raro a fim de invocar apenas os métodos aplicáveis a cada serviço específico. Se a associação for a classe BasicHttpBinding, não será possível dar suporte a vários níveis de proteção. No entanto, um serviço que responde ao cliente pode responder a um cliente com um nível de proteção menor do que o necessário. Nesse caso, o cliente lançará uma exceção, pois espera um nível de proteção mais alto.

Um exemplo do código ilustra esse problema. O exemplo a seguir mostra um serviço e um contrato de cliente. Vamos supor que a associação seja o elemento <basicHttpBinding>. Portanto, todas as operações em um contrato têm o mesmo nível de proteção. Esse nível de proteção uniforme é determinado como o nível máximo de proteção em todas as operações.

O contrato de serviço é:

[ServiceContract()]
public interface IPurchaseOrder
{
    [OperationContract(ProtectionLevel = ProtectionLevel.Sign)]
    int Price();
}
<ServiceContract()> _
Public Interface IPurchaseOrder
    <OperationContract(ProtectionLevel:=ProtectionLevel.Sign)> _
    Function Price() As Integer
End Interface

O código a seguir mostra a interface do contrato do cliente. Observe que ele inclui um método Tax que deve ser usado com um serviço diferente:

[ServiceContract()]
public interface IPurchaseOrder
{
    [OperationContract()]
    int Tax();

    [OperationContract(ProtectionLevel = ProtectionLevel.Sign)]
    int Price();
}
<ServiceContract()> _
Public Interface IPurchaseOrder
    <OperationContract()> _
    Function Tax() As Integer

    <OperationContract(ProtectionLevel:=ProtectionLevel.Sign)> _
    Function Price() As Integer
End Interface

Quando o cliente chama o método Price, ele gera uma exceção quando recebe uma resposta do serviço. Isso ocorre porque o cliente não especifica um ProtectionLevel no ServiceContractAttribute e, portanto, o cliente usa o padrão (EncryptAndSign) para todos os métodos, incluindo o método Price. No entanto, o serviço retorna o valor usando o nível Sign, pois o contrato de serviço define um único método que tem seu nível de proteção definido como Sign. Nesse caso, o cliente gerará um erro ao validar a resposta do serviço.

Confira também