Partilhar via


Endpoint de metadados seguros personalizados

O exemplo CustomMexEndpoint demonstra como implementar um serviço com um ponto de extremidade seguro para metadados que usa uma das associações sem suporte para troca de metadados e como configurar a ServiceModel Metadata Utility Tool (Svcutil.exe) ou clientes para obter os metadados desse ponto de extremidade. Há duas ligações fornecidas pelo sistema disponíveis para expor pontos de extremidade de metadados: mexHttpBinding e mexHttpsBinding. mexHttpBinding é usado para expor um ponto de extremidade de metadados sobre HTTP num formato não seguro. mexHttpsBinding é usado para expor um ponto de extremidade de metadados através de HTTPS de forma segura. Este exemplo ilustra como expor um ponto de extremidade de metadados seguro usando o WSHttpBinding. Você gostaria de fazer isso quando quiser alterar as configurações de segurança na associação, mas não deseja usar HTTPS. Se você usar o mexHttpsBinding, seu ponto de extremidade de metadados será seguro, mas não há como modificar as configurações de vinculação.

Observação

O procedimento de configuração e as instruções de compilação para este exemplo estão localizados no final deste tópico.

Serviço

O serviço neste exemplo tem duas interfaces. O endpoint da aplicação serve o ICalculator contrato em um WSHttpBinding com ReliableSession ativado e Message segurança através de certificados. O ponto de extremidade de metadados também usa WSHttpBinding, com as mesmas definições de segurança, mas sem ReliableSession. Aqui está a configuração relevante:

<services>
    <service name="Microsoft.ServiceModel.Samples.CalculatorService"
             behaviorConfiguration="CalculatorServiceBehavior">
     <!-- use base address provided by host -->
     <endpoint address=""
       binding="wsHttpBinding"
       bindingConfiguration="Binding2"
       contract="Microsoft.ServiceModel.Samples.ICalculator" />
     <endpoint address="mex"
       binding="wsHttpBinding"
       bindingConfiguration="Binding1"
       contract="IMetadataExchange" />
     </service>
 </services>
 <bindings>
   <wsHttpBinding>
     <binding name="Binding1">
       <security mode="Message">
         <message clientCredentialType="Certificate" />
       </security>
     </binding>
     <binding name="Binding2">
       <reliableSession inactivityTimeout="00:01:00" enabled="true" />
       <security mode="Message">
         <message clientCredentialType="Certificate" />
       </security>
     </binding>
   </wsHttpBinding>
 </bindings>

Em muitos dos outros exemplos, o endpoint de metadados usa o padrão mexHttpBinding, que não é seguro. Aqui os metadados são protegidos usando WSHttpBinding com Message segurança. Para que os clientes de metadados recuperem esses metadados, eles devem ser configurados com uma associação correspondente. Este exemplo demonstra dois desses clientes.

O primeiro cliente usa Svcutil.exe para buscar os metadados e gerar o código do cliente e a configuração em tempo de desenvolvimento. Como o serviço usa uma associação não padrão para os metadados, a ferramenta Svcutil.exe deve ser configurada especificamente para que possa obter os metadados do serviço usando essa ligação.

O segundo cliente usa o MetadataResolver para buscar dinamicamente os metadados de um contrato conhecido e, em seguida, invocar operações no cliente gerado dinamicamente.

Cliente Svcutil

Ao usar o binding padrão para hospedar o seu endpoint IMetadataExchange, pode executar Svcutil.exe com o endereço desse endpoint.

svcutil http://localhost/servicemodelsamples/service.svc/mex

e funciona. Mas neste exemplo, o servidor usa um ponto de extremidade não padrão para hospedar os metadados. Portanto, Svcutil.exe deve ser instruído a usar a vinculação correta. Isso pode ser feito usando um arquivo Svcutil.exe.config.

O arquivo Svcutil.exe.config se parece com um arquivo de configuração de cliente normal. Os únicos aspetos incomuns são o nome do ponto de extremidade do cliente e o contrato:

<endpoint name="http"
          binding="wsHttpBinding"
          bindingConfiguration="Binding1"
          behaviorConfiguration="ClientCertificateBehavior"
          contract="IMetadataExchange" />

O nome do ponto de extremidade deve ser o nome do esquema do endereço onde os metadados estão hospedados e o contrato do ponto de extremidade deve ser IMetadataExchange. Assim, quando Svcutil.exe é executado com uma linha de comando como a seguinte:

svcutil http://localhost/servicemodelsamples/service.svc/mex

Ele procura o ponto de extremidade chamado "HTTP" e o contrato IMetadataExchange para configurar a ligação e o comportamento da troca de comunicação com o ponto de extremidade de metadados. O restante do arquivo Svcutil.exe.config no exemplo especifica a configuração de ligação e os parâmetros de comportamento para corresponder à configuração do servidor do ponto de extremidade de metadados.

Para que Svcutil.exe pegue a configuração no Svcutil.exe.config, Svcutil.exe deve estar no mesmo diretório que o arquivo de configuração. Como resultado, você deve copiáSvcutil.exe de seu local de instalação para o diretório que contém o arquivo Svcutil.exe.config. Em seguida, a partir desse diretório, execute o seguinte comando:

.\svcutil.exe http://localhost/servicemodelsamples/service.svc/mex

O ".\" inicial garante que a cópia de Svcutil.exe neste diretório (aquele com um Svcutil.exe.configcorrespondente) seja executada.

Cliente MetadataResolver

Se o cliente conhece o contrato e como interagir com os metadados durante o tempo de design, o cliente pode encontrar dinamicamente o "binding" e o endereço dos pontos de extremidade da aplicação usando o MetadataResolver. Este cliente de exemplo demonstra isto, mostrando como configurar a ligação e as credenciais usadas por MetadataResolver, ao criar e configurar um MetadataExchangeClient.

As mesmas informações de vinculação e certificado que apareceram no Svcutil.exe.config podem ser especificadas imperativamente no MetadataExchangeClient:

// Specify the Metadata Exchange binding and its security mode
WSHttpBinding mexBinding = new WSHttpBinding(SecurityMode.Message);
mexBinding.Security.Message.ClientCredentialType = MessageCredentialType.Certificate;

// Create a MetadataExchangeClient for retrieving metadata, and set the // certificate details
MetadataExchangeClient mexClient = new MetadataExchangeClient(mexBinding);
mexClient.SoapCredentials.ClientCertificate.SetCertificate(    StoreLocation.CurrentUser, StoreName.My,
    X509FindType.FindBySubjectName, "client.com");
mexClient.SoapCredentials.ServiceCertificate.Authentication.CertificateValidationMode = X509CertificateValidationMode.PeerOrChainTrust;
mexClient.SoapCredentials.ServiceCertificate.SetDefaultCertificate(    StoreLocation.CurrentUser, StoreName.TrustedPeople,
    X509FindType.FindBySubjectName, "localhost");

Com o mexClient configurado, podemos enumerar os contratos em que estamos interessados e usar MetadataResolver para buscar uma lista de pontos finais com esses contratos:

// The contract we want to fetch metadata for
Collection<ContractDescription> contracts = new Collection<ContractDescription>();
ContractDescription contract = ContractDescription.GetContract(typeof(ICalculator));
contracts.Add(contract);
// Find endpoints for that contract
EndpointAddress mexAddress = new EndpointAddress(ConfigurationManager.AppSettings["mexAddress"]);
ServiceEndpointCollection endpoints = MetadataResolver.Resolve(contracts, mexAddress, mexClient);

Finalmente, podemos usar as informações desses pontos de extremidade para inicializar a vinculação e o endereço de um ChannelFactory usado para criar canais para comunicação com os pontos de extremidade do aplicativo.

ChannelFactory<ICalculator> cf = new ChannelFactory<ICalculator>(endpoint.Binding, endpoint.Address);

O ponto principal deste cliente de exemplo é demonstrar que, se estiver a usar MetadataResolver, e precisar especificar ligações ou comportamentos personalizados para a comunicação de troca de metadados, pode utilizar um MetadataExchangeClient para especificar essas configurações personalizadas.

Para configurar e compilar o exemplo

  1. Verifique se você executou o procedimento de instalação do One-Time para os exemplos do Windows Communication Foundation.

  2. Para criar a solução, siga as instruções em Criando os exemplos do Windows Communication Foundation.

Para executar a amostra na mesma máquina

  1. Execute Setup.bat a partir da pasta de instalação de exemplo. Isso instala todos os certificados necessários para executar o exemplo. Observe que o Setup.bat usa a ferramenta FindPrivateKey.exe, que é instalada executando setupCertTool.bat deOne-Time procedimento de instalação para os exemplos do Windows Communication Foundation.

  2. Execute o aplicativo cliente de \MetadataResolverClient\bin ou \SvcutilClient\bin. A atividade do cliente é exibida no aplicativo de console do cliente.

  3. Se o cliente e o serviço não puderem comunicar-se, consulte Dicas de Resolução de Problemas para Amostras de WCF.

  4. Remova os certificados executando Cleanup.bat quando terminar o exemplo. Outros exemplos de segurança usam os mesmos certificados.

Para executar o exemplo em várias máquinas

  1. No servidor, execute setup.bat service. A execução setup.bat com o service argumento cria um certificado de serviço com o nome de domínio totalmente qualificado da máquina e exporta o certificado de serviço para um arquivo chamado Service.cer.

  2. No servidor, editeWeb.config para refletir o nome do novo certificado. Ou seja, altere o atributo findValue no elemento <serviceCertificate> para o nome de domínio totalmente qualificado da máquina.

  3. Copie o arquivo Service.cer do diretório de serviço para o diretório do cliente na máquina cliente.

  4. No cliente, execute setup.bat client. A execução setup.bat com o client argumento cria um certificado de cliente chamado Client.com e exporta o certificado de cliente para um arquivo chamado Client.cer.

  5. No arquivo App.config da MetadataResolverClient máquina cliente, altere o valor de endereço do ponto de extremidade mex para corresponder ao novo endereço do seu serviço. Para fazer isso, substitua localhost pelo nome de domínio totalmente qualificado do servidor. Altere também a ocorrência de "localhost" no arquivo metadataResolverClient.cs para o novo nome de certificado de serviço (o nome de domínio totalmente qualificado do servidor). Faça a mesma coisa para o App.config do projeto SvcutilClient.

  6. Copie o arquivo Client.cer do diretório do cliente para o diretório de serviço no servidor.

  7. No cliente, execute ImportServiceCert.bat. Isso importa o certificado de serviço do arquivo Service.cer para o repositório CurrentUser - TrustedPeople.

  8. No servidor, execute ImportClientCert.bat, Isso importa o certificado do cliente do arquivo Client.cer para o armazenamento LocalMachine - TrustedPeople.

  9. Na máquina de serviço, crie o projeto de serviço no Visual Studio e selecione a página de ajuda em um navegador da Web para verificar se ele está em execução.

  10. Na máquina cliente, execute o MetadataResolverClient ou o SvcutilClient do VS.

    1. Se o cliente e o serviço não puderem comunicar-se, consulte Dicas de Resolução de Problemas para Amostras de WCF.

Para limpar após a amostra

  • Execute Cleanup.bat na pasta de exemplos depois de terminar de executar o exemplo.

    Observação

    Esse script não remove certificados de serviço em um cliente ao executar este exemplo em máquinas. Se você tiver executado exemplos do Windows Communication Foundation (WCF) que usam certificados entre máquinas, certifique-se de limpar os certificados de serviço que foram instalados no repositório CurrentUser - TrustedPeople. Para fazer isso, use o seguinte comando: certmgr -del -r CurrentUser -s TrustedPeople -c -n <Fully Qualified Server Machine Name>. Por exemplo: certmgr -del -r CurrentUser -s TrustedPeople -c -n server1.contoso.com.