Partilhar via


Segurança de mensagens com certificados mútuos

O cenário a seguir mostra um serviço WCF (Windows Communication Foundation) e um cliente protegido usando o modo de segurança de mensagem. O cliente e o serviço são autenticados com certificados.

Esse cenário é interoperável porque usa o WS-Security com o perfil de token de certificado X.509.

Nota

Este cenário não executa a negociação do certificado de serviço. O certificado de serviço deve ser fornecido ao cliente antes de qualquer comunicação. O certificado do servidor pode ser distribuído com o aplicativo ou fornecido em uma comunicação fora de banda.

Message security with mutual certificates

Characteristic Description
Modo de Segurança Mensagem
Interoperabilidade Sim, com clientes e serviços compatíveis com o perfil de token de certificado WS-Security e X.509.
Autenticação Autenticação mútua do servidor e do cliente.
Integridade Sim
Confidencialidade Sim
Transporte HTTP
Enlace WSHttpBinding

Serviço

O código e a configuração a seguir devem ser executados de forma independente. Execute um dos seguintes procedimentos:

  • Crie um serviço autônomo usando o código sem configuração.

  • Crie um serviço usando a configuração fornecida, mas não defina nenhum ponto de extremidade.

Código

O código a seguir mostra a criação de um ponto de extremidade de serviço que usa a segurança da mensagem. O serviço requer um certificado para se autenticar.

// Create the binding.
WSHttpBinding binding = new WSHttpBinding();
binding.Security.Mode = SecurityMode.Message;
binding.Security.Message.ClientCredentialType =
    MessageCredentialType.Certificate;
binding.Security.Message.NegotiateServiceCredential = false;
binding.Security.Message.EstablishSecurityContext = false;

// Create the URI for the endpoint.
Uri httpUri = new Uri("http://localhost/Calculator");

// Create the service host.
ServiceHost myServiceHost =
    new ServiceHost(typeof(Calculator), httpUri);

// Specify a certificate to authenticate the service.
myServiceHost.Credentials.ServiceCertificate.SetCertificate(
    StoreLocation.LocalMachine,
    StoreName.My,
    X509FindType.FindBySubjectName,
    "contoso.com");

// Add an endpoint to the service.
myServiceHost.AddServiceEndpoint(typeof(ICalculator), binding, "");

// Open the service.
myServiceHost.Open();
Console.WriteLine("Listening...");
Console.ReadLine();

// Close the service.
myServiceHost.Close();
' Create the binding.
Dim binding As New WSHttpBinding()
binding.Security.Mode = SecurityMode.Message
binding.Security.Message.ClientCredentialType = _
MessageCredentialType.Certificate
binding.Security.Message.NegotiateServiceCredential = False
binding.Security.Message.EstablishSecurityContext = False

' Create the URI for the endpoint.
Dim httpUri As New Uri("http://localhost/Calculator")

' Create the service host.
Dim myServiceHost As New ServiceHost(GetType(ServiceModel.Calculator), httpUri)

' Specify a certificate to authenticate the service.
myServiceHost.Credentials.ServiceCertificate.SetCertificate(StoreLocation.LocalMachine, _
StoreName.My, X509FindType.FindBySubjectName, "contoso.com")

' Add an endpoint to the service.
myServiceHost.AddServiceEndpoint(GetType(ICalculator), binding, "")

' Open the service.
myServiceHost.Open()
Console.WriteLine("Listening...")
Console.ReadLine()

' Close the service.
myServiceHost.Close()

Configuração

A configuração a seguir pode ser usada em vez do código para criar o mesmo serviço.

<?xml version="1.0" encoding="utf-8"?>  
<configuration>  
  <system.serviceModel>  
    <behaviors>  
      <serviceBehaviors>  
        <behavior name="serviceCredentialBehavior">  
          <serviceCredentials>  
            <serviceCertificate findValue="Contoso.com"
                                storeLocation="LocalMachine"  
                                storeName="My"
                                x509FindType="FindBySubjectName" />  
          </serviceCredentials>  
        </behavior>  
      </serviceBehaviors>  
    </behaviors>  
    <services>  
      <service behaviorConfiguration="serviceCredentialBehavior"
               name="ServiceModel.Calculator">  
        <endpoint address="http://localhost/Calculator"
                  binding="wsHttpBinding"  
                  bindingConfiguration="InteropCertificateBinding"  
                  name="WSHttpBinding_ICalculator"  
                  contract="ServiceModel.ICalculator" />  
      </service>  
    </services>  
    <bindings>  
      <wsHttpBinding>  
        <binding name="InteropCertificateBinding">  
          <security mode="Message">  
            <message clientCredentialType="Certificate"  
                     negotiateServiceCredential="false"  
                     establishSecurityContext="false" />  
          </security>  
        </binding>  
      </wsHttpBinding>  
    </bindings>  
    <client />  
  </system.serviceModel>  
</configuration>  

Cliente

O código e a configuração a seguir devem ser executados de forma independente. Execute um dos seguintes procedimentos:

  • Crie um cliente autônomo usando o código (e o código do cliente).

  • Crie um cliente que não defina nenhum endereço de ponto de extremidade. Em vez disso, use o construtor cliente que usa o nome da configuração como um argumento. Por exemplo:

    CalculatorClient cc = new CalculatorClient("EndpointConfigurationName");
    
    Dim cc As New CalculatorClient("EndpointConfigurationName")
    

Código

O código a seguir cria o cliente. O modo de segurança é definido como Mensagem e o tipo de credencial do cliente é definido como Certificado.

// Create the binding.
WSHttpBinding myBinding = new WSHttpBinding();
myBinding.Security.Mode = SecurityMode.Message;
myBinding.Security.Message.ClientCredentialType =
    MessageCredentialType.Certificate;

// Disable credential negotiation and the establishment of
// a security context.
myBinding.Security.Message.NegotiateServiceCredential = false;
myBinding.Security.Message.EstablishSecurityContext = false;

// Create the endpoint address.
EndpointAddress ea = new
    EndpointAddress("http://machineName/Calculator");

// Create the client.
CalculatorClient cc =
    new CalculatorClient(myBinding, ea);

// Specify a certificate to use for authenticating the client.
cc.ClientCredentials.ClientCertificate.SetCertificate(
    StoreLocation.CurrentUser,
    StoreName.My,
    X509FindType.FindBySubjectName,
    "Cohowinery.com");

// Specify a default certificate for the service.
cc.ClientCredentials.ServiceCertificate.SetDefaultCertificate(
    StoreLocation.CurrentUser,
    StoreName.TrustedPeople,
    X509FindType.FindBySubjectName,
    "Contoso.com");

// Begin using the client.
try
{
    cc.Open();
    Console.WriteLine(cc.Add(200, 1111));
    Console.ReadLine();

    // Close the client.
    cc.Close();
}
' Create the binding.
Dim myBinding As New WSHttpBinding()
myBinding.Security.Mode = SecurityMode.Message
myBinding.Security.Message.ClientCredentialType = MessageCredentialType.Certificate

' Disable credential negotiation and the establishment of
' a security context.
myBinding.Security.Message.NegotiateServiceCredential = False
myBinding.Security.Message.EstablishSecurityContext = False

' Create the endpoint address.
Dim ea As New EndpointAddress("http://localhost/Calculator")

' Create the client.
Dim cc As New CalculatorClient(myBinding, ea)

' Specify a certificate to use for authenticating the client.
cc.ClientCredentials.ClientCertificate.SetCertificate( _
    StoreLocation.CurrentUser, StoreName.My, _
    X509FindType.FindBySubjectName, "Cohowinery.com")

' Specify a default certificate for the service.
cc.ClientCredentials.ServiceCertificate.SetDefaultCertificate( _
    StoreLocation.CurrentUser, StoreName.TrustedPeople, _
    X509FindType.FindBySubjectName, "Contoso.com")

' Begin using the client.
Try
    cc.Open()

    Console.WriteLine(cc.Add(100, 11))
    Console.ReadLine()

    ' Close the client.
    cc.Close()
Catch tex As TimeoutException
    Console.WriteLine(tex.Message)
    cc.Abort()
Catch cex As CommunicationException
    Console.WriteLine(cex.Message)
    cc.Abort()
Finally
    Console.WriteLine("Closed the client")
    Console.ReadLine()
End Try

Configuração

O seguinte configura o cliente. Um certificado de cliente deve ser especificado usando clientCertificate><. Além disso, o certificado de serviço é especificado usando defaultCertificate><.

<?xml version="1.0" encoding="utf-8"?>  
<configuration>  
  <system.serviceModel>  
    <behaviors>  
      <endpointBehaviors>  
        <behavior name="ClientCredentialsBehavior">  
          <clientCredentials>  
            <clientCertificate findValue="Cohowinery.com"
                 storeLocation="CurrentUser"  
                 storeName="My"  
                 x509FindType="FindBySubjectName" />  
            <serviceCertificate>  
              <defaultCertificate findValue="Contoso.com"
                                  storeLocation="CurrentUser"  
                                  storeName="TrustedPeople"  
                                  x509FindType="FindBySubjectName" />  
            </serviceCertificate>  
          </clientCredentials>  
        </behavior>  
      </endpointBehaviors>  
    </behaviors>  
    <bindings>  
      <wsHttpBinding>  
        <binding name="WSHttpBinding_ICalculator" >  
          <security mode="Message">  
            <message clientCredentialType="Certificate"
                     negotiateServiceCredential="false"  
                     establishSecurityContext="false" />  
          </security>  
        </binding>  
      </wsHttpBinding>  
    </bindings>  
    <client>  
      <endpoint address="http://machineName/Calculator"
                behaviorConfiguration="ClientCredentialsBehavior"  
                binding="wsHttpBinding"
                bindingConfiguration="WSHttpBinding_ICalculator"  
                contract="ICalculator"  
                name="WSHttpBinding_ICalculator">  
        <identity>  
          <certificate encodedValue="Encoded_Value_Not_Shown" />  
        </identity>  
      </endpoint>  
    </client>  
  </system.serviceModel>  
</configuration>  

Consulte também