Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
Este tópico descreve as tarefas de programação fundamentais usadas para criar um aplicativo seguro do WCF (Windows Communication Foundation). Este tópico aborda apenas autenticação, confidencialidade e integridade, coletivamente conhecida como segurança de transferência. Este tópico não aborda a autorização (o controle de acesso a recursos ou serviços); para obter informações sobre autorização, consulte Autorização.
Observação
Para obter uma introdução valiosa aos conceitos de segurança, especialmente no que diz respeito ao WCF, consulte o conjunto de tutoriais de padrões e práticas no MSDN em Cenários, Padrões e Diretrizes de Implementação para Aprimoramentos de Serviços Web (WSE) 3.0.
A programação da segurança do WCF baseia-se em três etapas definindo o seguinte: o modo de segurança, um tipo de credencial de cliente e os valores de credenciais. Você pode executar essas etapas por meio do código ou da configuração.
Definindo o modo de segurança
O seguinte explica as etapas gerais para programação com o modo de segurança no WCF:
Selecione uma das associações predefinidas apropriadas aos requisitos do aplicativo. Para obter uma lista das opções de associação, consulte System-Provided Associações. Por padrão, quase todas as associações têm a segurança habilitada. A única exceção é a classe BasicHttpBinding (usando configuração, a <basicHttpBinding>).
A associação selecionada determina o transporte. Por exemplo, WSHttpBinding usa HTTP como transporte; NetTcpBinding usa TCP.
Selecione um dos modos de segurança para a associação. Observe que a associação selecionada determina as opções de modo disponíveis. Por exemplo, o WSDualHttpBinding não permite segurança de transporte (não é uma opção). Da mesma forma, nem o MsmqIntegrationBinding nem o NetNamedPipeBinding permitem segurança de mensagem.
Você tem três opções:
TransportA segurança do transporte depende do mecanismo que a associação que você selecionou usa. Por exemplo, se você estiver usando
WSHttpBinding, o mecanismo de segurança será SSL (Secure Sockets Layer) (também o mecanismo para o protocolo HTTPS). De um modo geral, a principal vantagem da segurança de transporte é que ela fornece boa taxa de transferência, independentemente do transporte que você está usando. No entanto, ele tem duas limitações: a primeira é que o mecanismo de transporte determina o tipo de credencial usado para autenticar um usuário. Essa é uma desvantagem somente se um serviço precisar interoperar com outros serviços que exigem diferentes tipos de credenciais. A segunda é que, como a segurança não é aplicada no nível da mensagem, a segurança é implementada de maneira salto a salto, em vez de de ponta a ponta. Essa última limitação será um problema somente se o caminho da mensagem entre o cliente e o serviço incluir intermediários. Para obter mais informações sobre qual transporte usar, consulte Escolhendo um transporte. Para obter mais informações sobre como usar a segurança de transporte, consulte Visão geral de segurança de transporte.MessageA segurança da mensagem significa que cada mensagem inclui os cabeçalhos e dados necessários para manter a mensagem segura. Como a composição dos cabeçalhos varia, você pode incluir qualquer número de credenciais. Isso se tornará um fator se você estiver interoperando com outros serviços que exigem um tipo de credencial específico que um mecanismo de transporte não pode fornecer ou se a mensagem deve ser usada com mais de um serviço, em que cada serviço exige um tipo de credencial diferente.
Para obter mais informações, consulte Segurança da Mensagem.
TransportWithMessageCredentialEssa opção usa a camada de transporte para proteger a transferência de mensagens, enquanto cada mensagem inclui as credenciais avançadas de que outros serviços precisam. Isso combina a vantagem de desempenho da segurança de transporte com a vantagem de credenciais avançadas da segurança da mensagem. Isso está disponível com as seguintes associações: BasicHttpBinding, , WSFederationHttpBindinge NetPeerTcpBindingWSHttpBinding.
Se você decidir usar a segurança de transporte para HTTP (em outras palavras, HTTPS), também deverá configurar o host com um certificado SSL e habilitar o SSL em uma porta. Para obter mais informações, consulte Segurança de Transporte HTTP.
Se você estiver usando o WSHttpBinding e não precisar estabelecer uma sessão segura, defina a propriedade EstablishSecurityContext como
false.Uma sessão segura ocorre quando um cliente e um serviço criam um canal usando uma chave simétrica (cliente e servidor usam a mesma chave para o comprimento de uma conversa, até que a caixa de diálogo seja fechada).
Definindo o tipo de credencial do cliente
Selecione um tipo de credencial de cliente conforme apropriado. Para obter mais informações, consulte Selecionar um tipo de credencial. Os seguintes tipos de credencial de cliente estão disponíveis:
WindowsCertificateDigestBasicUserNameNTLMIssuedToken
Dependendo de como você define o modo, você deve definir o tipo de credencial. Por exemplo, se você selecionou o wsHttpBinding e definiu o modo como "Mensagem", também poderá definir o atributo clientCredentialType do elemento Message como um dos seguintes valores: None, Windows, UserName, Certificate e IssuedToken, como mostrado no exemplo de configuração a seguir.
<system.serviceModel>
<bindings>
<wsHttpBinding>
<binding name="myBinding">
<security mode="Message"/>
<message clientCredentialType="Windows"/>
</binding>
</wsHttpBinding>
</bindings>
</system.serviceModel>
Ou no código:
WSHttpBinding b = new WSHttpBinding();
b.Name = "myBinding";
b.Security.Mode = SecurityMode.Message;
b.Security.Message.ClientCredentialType=MessageCredentialType.Windows;
Dim b As New WSHttpBinding()
b.Name = "myBinding"
b.Security.Mode = SecurityMode.Message
b.Security.Message.ClientCredentialType = MessageCredentialType.Windows
Configurando Valores de Credenciais de Serviço
Depois de selecionar um tipo de credencial de cliente, você deverá definir as credenciais reais para o serviço e o cliente usarem. No serviço, as credenciais são definidas usando a ServiceCredentials classe e retornadas pela Credentials propriedade da ServiceHostBase classe. A associação em uso implica o tipo de credencial de serviço, o modo de segurança escolhido e o tipo da credencial do cliente. O código a seguir define um certificado para uma credencial de serviço.
// Create the binding for an endpoint.
NetTcpBinding b = new NetTcpBinding();
b.Security.Mode = SecurityMode.Message;
// Create the ServiceHost for a calculator.
Uri baseUri = new Uri("net.tcp://MachineName/tcpBase");
Uri[] baseAddresses = new Uri[] { baseUri };
ServiceHost sh = new ServiceHost(typeof(Calculator), baseAddresses);
// Add an endpoint using the binding and a new address.
Type c = typeof(ICalculator);
sh.AddServiceEndpoint(c, b, "MyEndpoint");
// Set a certificate as the credential for the service.
sh.Credentials.ServiceCertificate.SetCertificate(
StoreLocation.LocalMachine,
StoreName.My,
X509FindType.FindBySubjectName,
"client.com");
try
{
sh.Open();
Console.WriteLine("Listening....");
Console.ReadLine();
sh.Close();
}
catch (CommunicationException ce)
{
Console.WriteLine($"A communication error occurred: {ce.Message}");
Console.WriteLine();
}
catch (System.Exception exc)
{
Console.WriteLine($"An unforeseen error occurred: {exc.Message}");
Console.ReadLine();
}
' Create the binding for an endpoint.
Dim b As New NetTcpBinding()
b.Security.Mode = SecurityMode.Message
' Create the ServiceHost for a calculator.
Dim baseUri As New Uri("net.tcp://MachineName/tcpBase")
Dim baseAddresses() As Uri = {baseUri}
Dim sh As New ServiceHost(GetType(Calculator), baseAddresses)
' Add an endpoint using the binding and a new address.
Dim c As Type = GetType(ICalculator)
sh.AddServiceEndpoint(c, b, "MyEndpoint")
' Set a certificate as the credential for the service.
sh.Credentials.ServiceCertificate.SetCertificate( _
StoreLocation.LocalMachine, _
StoreName.My, _
X509FindType.FindBySubjectName, _
"contoso.com")
Try
sh.Open()
Console.WriteLine("Listening....")
Console.ReadLine()
sh.Close()
Catch ce As CommunicationException
Console.WriteLine("A communication error occurred: {0}", ce.Message)
Console.WriteLine()
Catch exc As System.Exception
Console.WriteLine("An unforeseen error occurred: {0}", exc.Message)
Console.ReadLine()
End Try
Definindo valores de credencial do cliente
No cliente, defina os valores das credenciais do cliente usando a classe ClientCredentials e retorne pela propriedade ClientCredentials da classe ClientBase<TChannel>. O código a seguir define um certificado como uma credencial em um cliente usando o protocolo TCP.
// Create a NetTcpBinding and set its security properties. The
// security mode is Message, and the client must be authenticated with
// Windows. Therefore the client must be on the same Windows domain.
NetTcpBinding b = new NetTcpBinding();
b.Security.Mode = SecurityMode.Message;
b.Security.Message.ClientCredentialType = MessageCredentialType.Windows;
// Set a Type variable for use when constructing the endpoint.
Type c = typeof(ICalculator);
// Create a base address for the service.
Uri tcpBaseAddress =
new Uri("net.tcp://machineName.Domain.Contoso.com:8036/serviceName");
// The base address is in an array of URI objects.
Uri[] baseAddresses = new Uri[] { tcpBaseAddress };
// Create the ServiceHost with type and base addresses.
ServiceHost sh = new ServiceHost(typeof(CalculatorClient), baseAddresses);
// Add an endpoint to the service using the service type and binding.
sh.AddServiceEndpoint(c, b, "");
sh.Open();
string address = sh.Description.Endpoints[0].ListenUri.AbsoluteUri;
Console.WriteLine($"Listening @ {address}");
Console.WriteLine("Press enter to close the service");
Console.ReadLine();
' Create a NetTcpBinding and set its security properties. The
' security mode is Message, and the client must be authenticated with
' Windows. Therefore the client must be on the same Windows domain.
Dim b As New NetTcpBinding()
b.Security.Mode = SecurityMode.Message
b.Security.Message.ClientCredentialType = MessageCredentialType.Windows
' Set a Type variable for use when constructing the endpoint.
Dim c As Type = GetType(ICalculator)
' Create a base address for the service.
Dim tcpBaseAddress As New Uri("net.tcp://machineName.Domain.Contoso.com:8036/serviceName")
' The base address is in an array of URI objects.
Dim baseAddresses() As Uri = {tcpBaseAddress}
' Create the ServiceHost with type and base addresses.
Dim sh As New ServiceHost(GetType(CalculatorClient), baseAddresses)
' Add an endpoint to the service using the service type and binding.
sh.AddServiceEndpoint(c, b, "")
sh.Open()
Dim address As String = sh.Description.Endpoints(0).ListenUri.AbsoluteUri
Console.WriteLine("Listening @ {0}", address)
Console.WriteLine("Press enter to close the service")
Console.ReadLine()