Como: proteger pontos de extremidade de metadados

Os metadados de um serviço podem conter informações confidenciais sobre seu aplicativo que um usuário mal-intencionado pode aproveitar. Os consumidores do serviço também podem exigir um mecanismo seguro para obter metadados sobre seu serviço. Portanto, às vezes é necessário publicar seus metadados usando um ponto de extremidade seguro.

Os pontos de extremidade de metadados geralmente são protegidos usando os mecanismos de segurança padrão definidos no WCF (Windows Communication Foundation) para proteger pontos de extremidade do aplicativo. Para obter mais informações, consulte Visão geral de segurança.

Este tópico percorre as etapas para criar um ponto de extremidade protegido por um certificado SSL (Secure Sockets Layer) ou, em outras palavras, um ponto de extremidade HTTPS.

Para criar um ponto de extremidade de metadados HTTPS GET seguro no código

  1. Configure uma porta com um certificado X.509 apropriado. O certificado deve vir de uma autoridade confiável e deve ter um uso pretendido de "Autorização de Serviço". Você deve usar a ferramenta HttpCfg.exe para anexar o certificado à porta. Confira Como configurar uma porta com um certificado SSL.

    Importante

    O assunto do certificado ou seu DNS (Sistema de Nomes de Domínio) deve corresponder ao nome do computador. Isso é essencial porque uma das primeiras etapas executadas pelo mecanismo HTTPS é verificar se o certificado é emitido para o mesmo URI (Uniform Resource Identifier) que o endereço no qual ele é invocado.

  2. Crie uma nova instância da classe ServiceMetadataBehavior.

  3. Defina a propriedade HttpsGetEnabled da classe ServiceMetadataBehavior como true.

  4. Defina a propriedade HttpsGetUrl com uma URL apropriada. Observe que, se você especificar um endereço absoluto, a URL deverá iniciar com o esquema https://. Se você especificar um endereço relativo, deverá fornecer um endereço base HTTPS para o host de serviço. Se essa propriedade não estiver definida, o endereço padrão será "", ou diretamente no endereço base HTTPS do serviço.

  5. Adicione a instância à coleção de comportamentos que a propriedade Behaviors da classe ServiceDescription retornar, conforme mostrado no código a seguir.

    // Create a new metadata behavior object and set its properties to
    // create a secure endpoint.
    ServiceMetadataBehavior sb = new ServiceMetadataBehavior();
    sb.HttpsGetEnabled = true;
    sb.HttpsGetUrl = new Uri("https://myMachineName:8036/myEndpoint");
    myServiceHost.Description.Behaviors.Add(sb);
    
    myServiceHost.Open();
    
    ' Create a new metadata behavior object and set its properties to 
    ' create a secure endpoint. 
    Dim sb As New ServiceMetadataBehavior()
    
    With sb
        .HttpsGetEnabled = True
        .HttpsGetUrl = New Uri("https://myMachineName:8036/myEndpoint")
    End With
    
    With myServiceHost
        .Description.Behaviors.Add(sb)
        .Open()
    End With
    

Para criar um ponto de extremidade de metadados HTTPS GET seguro na configuração

  1. Adicione um elemento de <comportamentos> ao elemento <system.serviceModel> do arquivo de configuração do seu serviço.

  2. Adicione um elemento <serviceBehaviors> ao elemento de <comportamentos>.

  3. Adicione um elemento de <comportamento> ao elemento <serviceBehaviors>.

  4. Defina o atributo name do elemento <behavior> com um valor apropriado. O atributo name é necessário. O exemplo a seguir usa o valor mySvcBehavior.

  5. Adicione um <serviceMetadata> ao elemento <behavior>.

  6. Defina o atributo httpsGetEnabled do elemento <serviceMetadata> como true.

  7. Defina o atributo httpsGetUrl do elemento <serviceMetadata> com um valor apropriado. Observe que, se você especificar um endereço absoluto, a URL deverá iniciar com o esquema https://. Se você especificar um endereço relativo, deverá fornecer um endereço base HTTPS para o host de serviço. Se essa propriedade não estiver definida, o endereço padrão será "", ou diretamente no endereço base HTTPS do serviço.

  8. Para usar o comportamento com um serviço, defina o atributo behaviorConfiguration do elemento de <serviço> como o valor do atributo de nome do elemento de comportamento. O código de configuração a seguir mostra um exemplo completo.

    <?xml version="1.0" encoding="utf-8" ?>
    <configuration>
     <system.serviceModel>
      <behaviors>
       <serviceBehaviors>
        <behavior name="mySvcBehavior">
         <serviceMetadata httpsGetEnabled="true"
              httpsGetUrl="https://localhost:8036/calcMetadata" />
        </behavior>
       </serviceBehaviors>
      </behaviors>
     <services>
      <service behaviorConfiguration="mySvcBehavior"
            name="Microsoft.Security.Samples.Calculator">
       <endpoint address="http://localhost:8037/ServiceModelSamples/calculator"
       binding="wsHttpBinding" bindingConfiguration=""
       contract="Microsoft.Security.Samples.ICalculator" />
      </service>
     </services>
    </system.serviceModel>
    </configuration>
    

Exemplo

O exemplo a seguir cria uma instância de uma classe ServiceHost e adiciona um ponto de extremidade. Em seguida, o código cria uma instância da classe ServiceMetadataBehavior e define as propriedades para criar um ponto de troca de metadados seguro.

WSHttpBinding myBinding = new WSHttpBinding();
myBinding.Security.Mode = SecurityMode.Message;
myBinding.Security.Message.ClientCredentialType =
    MessageCredentialType.Windows;

// Create the Type instances for later use and the URI for
// the base address.
Type contractType = typeof(ICalculator);
Type serviceType = typeof(Calculator);
Uri baseAddress = new
    Uri("http://localhost:8037/serviceModelSamples/");

// Create the ServiceHost and add an endpoint.
ServiceHost myServiceHost =
    new ServiceHost(serviceType, baseAddress);
myServiceHost.AddServiceEndpoint
    (contractType, myBinding, "secureCalculator");
// Create a new metadata behavior object and set its properties to
// create a secure endpoint.
ServiceMetadataBehavior sb = new ServiceMetadataBehavior();
sb.HttpsGetEnabled = true;
sb.HttpsGetUrl = new Uri("https://myMachineName:8036/myEndpoint");
myServiceHost.Description.Behaviors.Add(sb);

myServiceHost.Open();
// Use the GetHostEntry method to return the actual machine name.
string machineName = System.Net.Dns.GetHostEntry("").HostName ;
Console.WriteLine("Listening @ {0}:8037/serviceModelSamples/", machineName);
Console.WriteLine("Press Enter to close the service");
Console.ReadLine();
myServiceHost.Close();
Dim myBinding As New WSHttpBinding()
With myBinding.Security
    .Mode = SecurityMode.Message
    .Message.ClientCredentialType = MessageCredentialType.Windows
End With

' Create the Type instances for later use and the URI for 
' the base address.
Dim contractType = GetType(ICalculator)
Dim serviceType = GetType(Calculator)
Dim baseAddress As New Uri("http://localhost:8037/serviceModelSamples/")

' Create the ServiceHost and add an endpoint. 
Dim myServiceHost As New ServiceHost(serviceType, baseAddress)
myServiceHost.AddServiceEndpoint(contractType, myBinding, "secureCalculator")

' Create a new metadata behavior object and set its properties to 
' create a secure endpoint. 
Dim sb As New ServiceMetadataBehavior()

With sb
    .HttpsGetEnabled = True
    .HttpsGetUrl = New Uri("https://myMachineName:8036/myEndpoint")
End With

With myServiceHost
    .Description.Behaviors.Add(sb)
    .Open()
End With

' Use the GetHostEntry method to return the actual machine name.
Dim machineName = System.Net.Dns.GetHostEntry("").HostName
Console.WriteLine("Listening @ {0}:8037/serviceModelSamples/", machineName)
Console.WriteLine("Press Enter to close the service")
Console.ReadLine()
myServiceHost.Close()

Compilando o código

O exemplo de código usa os seguintes namespaces:

Confira também