Partilhar via


Ponto de extremidade de metadados seguros personalizados

O exemplo CustomMexEndpoint demonstra como implementar um serviço com um ponto de extremidade de metadados seguro que usa uma das associações de troca de metadados que não são metadados e como configurar a ServiceModel Metadata Utility Tool (Svcutil.exe) ou clientes para buscar os metadados de tal ponto de extremidade de metadados. 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 de forma não segura. mexHttpsBinding é usado para expor um ponto de extremidade de metadados por 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.

Nota

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 dois pontos de extremidade. O ponto de extremidade do aplicativo serve o ICalculator contrato em um WSHttpBinding com ReliableSession habilitado e Message segurança usando certificados. O ponto de extremidade de metadados também usa WSHttpBinding, com as mesmas configuraçõ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 ponto de extremidade 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 código e configuração do cliente em tempo de design. 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 associaçã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 a associação padrão para hospedar seu IMetadataExchange ponto de extremidade, você pode executar Svcutil.exe com o endereço desse ponto de extremidade:

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 normal do cliente. 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 vinculação e as credenciais 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 copiar 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 ".\" à esquerda garante que a cópia de Svcutil.exe neste diretório (aquele que tem um Svcutil.exe.config correspondente) seja executada.

Cliente MetadataResolver

Se o cliente conhece o contrato e como falar com os metadados em tempo de design, o cliente pode descobrir dinamicamente a ligação e o endereço dos pontos de extremidade do aplicativo usando o MetadataResolver. Este cliente de exemplo demonstra isso, mostrando como configurar a associação e as credenciais usadas criando MetadataResolver e configurando um MetadataExchangeClientarquivo .

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 ligação e o endereço de um ChannelFactory usado para criar canais para se comunicar com os pontos de extremidade do aplicativo.

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

O ponto-chave deste cliente de exemplo é demonstrar que, se você estiver usando MetadataResolvero , e precisar especificar associações ou comportamentos personalizados para a comunicação de troca de metadados, poderá usar um MetadataExchangeClient para especificar essas configurações personalizadas.

Para configurar e compilar o exemplo

  1. Certifique-se de ter executado o procedimento de instalação única 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 Setup.bat usa a ferramenta FindPrivateKey.exe, que é instalada executando setupCertTool.bat do procedimento de instalação única 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 se comunicar, consulte Dicas de solução de problemas para exemplos de WCF.

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

Para executar a amostra em 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, edite Web.config para refletir o novo nome do certificado. Ou seja, altere o findValue<atributo 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 máquina cliente, altere MetadataResolverClient 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 se comunicar, consulte Dicas de solução de problemas para exemplos de WCF.

Para limpar após a amostra

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

    Nota

    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.