Compartilhar via


Como: Use a segurança de transporte

The .NET Compact Framework versão 3.5 oferece suporte ao uso de transporte HTTPS para se conectar a um Windows Communication Foundation (WCF) serviço na área de trabalho. Ele inclui suporte para autenticação do servidor e autenticação de cliente.

Este tópico fornece um exemplo de configuração do serviço e mostra como modificar o código do cliente para autenticação mútua.

Observação:

Para servidor autenticação, não é necessário um certificado de cliente.Também há suporte para segurança de mensagem i n o .NET Compact Framework 3,5, mas não é usado neste exemplo.

Para criar o serviço WCF para a área de trabalho

  1. Criar e instalar um certificado de servidor e um certificado de cliente.

    Essas etapas são específicas para a ferramenta de geração de certificado que você está usando (por exemplo, Makecert.exe) e estão além do escopo deste tópico.As tarefas a seguir será necessárias:

    • criar uma auto-assinada de certificados e nomeie-o (por exemplo, use o nome da sua empresa: da empresa).

    • Criar um certificado de servidor assinado por da empresa.O nome do certificado do servidor deve corresponder ao nome do host URL usado para acessar o serviço

    • Criar um certificado de cliente assinado por da empresa.

    Observação:

    Recomendamos que você instalar o certificado do servidor para o computador local em vez de Instalando-o para o usuário corrente.Caso contrário, se o serviço hospedado no Serviços de Informações da Internet) IIS ) e instale-o para o usuário corrente, ele não funcionará.

  2. Crie um novo projeto de serviço Web.

  3. Substitua o arquivo Web.config pelo exemplo mostrado nesta etapa.Modificar os elementos e atributos do seguinte:

    • Alterar o service name atributo para o novo serviço que você está usando.

    • Alterar o behaviorConfiguration atributo para referir-se o nome do novo comportamento.

    • Alterar o endpoint contract atributo para referir-se a interface do serviço.

    Observação:

    Tornar -se de que o binding atributo de valor para o <endpoint>o elemento é "basicHttpBinding". The .NET Compact Framework oferece suporte à codificação de texto, mas a codificação binária não.

    <?xml version="1.0" encoding="utf-8" ?>
    <configuration>
      <system.serviceModel>
        <services>
          <service 
              name="CalculatorService"
              behaviorConfiguration="MyServiceTypeBehaviors">
            <endpoint address=""
                      binding="basicHttpBinding"
                      bindingConfiguration="transport"
                      contract="ICalculatorService" />
            <endpoint address="mex"
                      binding="basicHttpBinding"
                      bindingConfiguration="transport"
                      contract="IMetadataExchange" />
          </service>
        </services>
        <bindings>
          <basicHttpBinding>
            <binding name="transport">
              <security mode="Transport">
                <transport clientCredentialType="Certificate" />
              </security>
            </binding>
          </basicHttpBinding>
        </bindings>
        <!--For debugging purposes set the includeExceptionDetailInFaults attribute to true-->
        <behaviors>
          <serviceBehaviors>
            <behavior name="MyServiceTypeBehaviors">
              <serviceMetadata httpsGetEnabled="True" httpsGetUrl=""/>
              <serviceDebug includeExceptionDetailInFaults="False" />
              <serviceCredentials>
                <clientCertificate>
                   <authentication trustedStoreLocation="LocalMachine"
                               revocationMode="NoCheck"
                               certificateValidationMode="ChainTrust"/>
                </clientCertificate>
              </serviceCredentials>
            </behavior>
          </serviceBehaviors>
        </behaviors>
    
      </system.serviceModel>
    
    </configuration>
    
  4. No código fonte para o serviço WCF, remova os parâmetros especificados no ServiceContract e OperationContract atributos do seu código.

    Observação:

    Esta amostra não implementa suporte para parâmetros especificado em contratos, sistema autônomo ServiceContract e OperationContract.Se você precisar de suporte ao parâmetro para esses contratos, você pode usar o WCF .NET Compact Framework Ferramenta Utilitário de ServiceModel (NetCFSvcUtil.exe) para gerar o código do cliente. Essa ferramenta cria o suporte para muitos desses parâmetros em aplicativos que sejam baseiam o .NET Compact Framework. NetCFSvcUtil.exe está disponível no potência Toys para .NET Compact Framework. Para obter mais informações, consulte potência Toys para o .NET Compact estrutura.

    O exemplo a seguir mostra o código de fonte do serviço WCF para um aplicativo de calculadora simplificada.

    <ServiceContract()>  _
    Public Interface ICalculatorService
        <OperationContract()>  _
        Function Add(ByVal n1 As Double, ByVal n2 As Double) As Double 
        '<OperationContract()>  _
        Function Subtract(ByVal n1 As Double, ByVal n2 As Double) As Double
    End Interface
    
    
    Public Class CalculatorService
        Implements ICalculatorService
    
        Public Function Add(ByVal n1 As Double, ByVal n2 As Double) As Double Implements ICalculatorService.Add
            Return n1 + n2
    
        End Function
    
        Public Function Subtract(ByVal n1 As Double, ByVal n2 As Double) As Double Implements ICalculatorService.Subtract
            Return n1 - n2
    
        End Function
    End Class
    
    [ServiceContract()]
    public interface ICalculatorService
    {
        [OperationContract]
        double Add(double n1, double n2);
        [OperationContract]
        double Subtract(double n1, double n2);
    }
    
    public class CalculatorService : ICalculatorService
    {
        public double Add(double n1, double n2) { return n1 + n2; }
        public double Subtract(double n1, double n2) { return n1 - n2; }
    }
    
  5. criar um site ou diretório virtual e seu projeto de serviço Web de referência.No servidor Web, configurar o serviço exigir HTTPS e um certificado de cliente.

    Observação:

    No IIS, você deve especificar o certificado do servidor e o certificado de cliente.

  6. Inicie o servidor Web.

    Se você deseja exibir a saída de WSDL (linguagem WSDL) e executar o serviço no host local, navegue até https://localhost/CalculatorService/Service.svc?wsdl.Use o mesmo nome de projeto Web que você especificou para o serviço do WCF.

  7. Verifique se que você pode acesso a pasta a partir de um navegador área de trabalho e um navegador de dispositivo usando HTTPS.

    Você deve certificar-se de que os certificados são configurados corretamente antes de poder acessar o serviço.O servidor Web também precise ser configurado para manipular as solicitações para um serviço WCF.

Para criar o cliente .NET Compact estrutura

  1. Enquanto o serviço está em execução, abra uma linha de comando e navegar até o diretório onde se encontra o serviço do WCF.

  2. Da linha de comando, execute a ferramenta Utilitário de área de trabalho de ServiceModel WCF (SvcUtil.exe) para gerar um proxy de cliente do WCF.O exemplo a seguir mostra a invocação da linha de comando para SvcUtil em que o serviço é hospedado no host local:

    svcutil.exe /language:c# https://localhost/CalculatorService/Service.svc
    
  3. Remova elementos e atributos não suportados do código de proxy gerados do cliente, incluindo o seguinte:

    • All System.ServiceModel atributos.

    • Referências à IClientChannel classe.

    • Referências a <endpoint> nomes de configuração.

    • Implementações de método que telefonar métodos do ServiceContract interface de canal internos.

    Para obter um exemplo desta etapa, consulte Como: Usar o transporte HTTP.

  4. Crie um projeto de cliente.

  5. Adicione o proxy de cliente gerada para o projeto.

  6. No código proxy gerado, alterar a referência totalmente qualificado de ClientBase<TChannel> definido o usuário ClientBase classe.

  7. No código proxy gerado, adicione implementações do método invocando o Call método em definido do usuário ClientBase classe.

    Public Function Add(ByVal n1 As Double, ByVal n2 As Double) As Double Implements ICalculatorService.Add
        Return System.Convert.ToDouble(MyBase.Call("Add", "https://fabrikam.com/CalcService/ICalculatorService/Add", New String() {"n1", "n2"}, New Object() {n1, n2}, GetType(Double)))
    
    End Function
    
    public double Add(double n1, double n2)
    {
        return (double)base.Call("Add", "https://fabrikam.com/CalcService/ICalculatorService/Add", new string[] { "n1", "n2" }, new object[] { n1, n2 }, typeof(double));
    }
    
  8. Adicione a classe base para o proxy para o projeto.Essa classe é nomeada ClientBase.

    Altere a referência da classe base de seu proxy de cliente para apontar para sua implementação de ClientBase.

    Observação:

    Neste exemplo, o CustomBodyWriter classe na ClientBase oferece suporte somente tipos primitivos. Para oferecer suporte a tipos de não-primitivo, é necessário estender o OnWriteBodyContents método. Por exemplo, você poderia chamar um serializador personalizado para serializar os dados da mensagem.Nesse caso, você poderia traduzir código atributos no proxy do cliente gerado atributos que pode consumir o serializador do XML.Nesse cenário, primeiro você deve adicionar a seguinte comutador quando você executa o SvcUtil: /serializer:xmlserializer http://ponto de extremidade.

    O código a seguir mostra um exemplo do ClientBase classe. A ClientCredentials o objeto é usado para especificar o certificado X.509 usado pelo cliente, que é nomeado testuser Neste exemplo.

    Public Class ClientBase(Of TChannel As Class)
    
        Private requestChannel As IRequestChannel
        Private messageVersion As MessageVersion
    
    
        Public Sub New(ByVal binding As System.ServiceModel.Channels.Binding, ByVal remoteAddress As System.ServiceModel.EndpointAddress)
            'this.remoteAddress = remoteAddress;
            Me.messageVersion = binding.MessageVersion
    
            Dim parameters = New System.ServiceModel.Channels.BindingParameterCollection()
    
            ' Specifies the X.509 certificate used by the client.
            Dim cc As New ClientCredentials()
            cc.ClientCertificate.SetCertificate(StoreLocation.CurrentUser, StoreName.My, X509FindType.FindBySubjectName, "testuser")
            parameters.Add(cc)
    
            Dim channelFactory As IChannelFactory(Of IRequestChannel)
            channelFactory = binding.BuildChannelFactory(Of IRequestChannel)(parameters)
            channelFactory.Open()
            Me.requestChannel = channelFactory.CreateChannel(remoteAddress)
    
        End Sub
    
    
        Public Function [Call](ByVal op As String, ByVal action As String, ByVal varnames() As String, ByVal varvals() As Object, ByVal returntype As Type) As Object
            requestChannel.Open(TimeSpan.MaxValue)
    
            'Message msg =
            'Message.CreateMessage(MessageVersion.<FromBinding>,
            '      action,
            '      new CustomBodyWriter(op, varnames, varvals,
            '"<ns passed in from Proxy>"));
            Dim msg As Message = Message.CreateMessage(Me.messageVersion, action, New CustomBodyWriter(op, varnames, varvals, "<ns passed in from Proxy>"))
    
            Dim reply As Message = requestChannel.Request(msg, TimeSpan.MaxValue)
            Dim reader As XmlDictionaryReader = reply.GetReaderAtBodyContents()
            reader.ReadToFollowing(op + "Result")
            Return reader.ReadElementContentAs(returntype, Nothing)
    
        End Function
    End Class
    
    
    Friend Class CustomBodyWriter
        Inherits BodyWriter
        Private op As String
        Private varnames() As String
        Private varvals() As Object
        Private ns As String
    
    
        Public Sub New(ByVal op As String, ByVal varnames() As String, ByVal varvals() As Object, ByVal ns As String)
            MyBase.New(True)
            Me.op = op
            Me.varnames = varnames
            Me.varvals = varvals
            Me.ns = ns
    
        End Sub
    
    
        Protected Overrides Sub OnWriteBodyContents(ByVal writer As XmlDictionaryWriter)
            writer.WriteStartElement(op, ns)
            Dim i As Integer
            For i = 0 To varnames.Length
                writer.WriteElementString(varnames(i), varvals(i).ToString())
            Next i
            writer.WriteEndElement()
    
        End Sub
    End Class
    
    public class ClientBase<TChannel>
        where TChannel : class
    {
        private IRequestChannel requestChannel;
        private MessageVersion messageVersion;
    
        public ClientBase(System.ServiceModel.Channels.Binding binding, System.ServiceModel.EndpointAddress remoteAddress)
        {
            //this.remoteAddress = remoteAddress;
            this.messageVersion = binding.MessageVersion;
    
            BindingParameterCollection parameters = new System.ServiceModel.Channels.BindingParameterCollection();
    
            // Specifies the X.509 certificate used by the client.
            ClientCredentials cc = new ClientCredentials();
            cc.ClientCertificate.SetCertificate(StoreLocation.CurrentUser, StoreName.My, X509FindType.FindBySubjectName, "testuser");
            parameters.Add(cc);
    
            IChannelFactory<IRequestChannel> channelFactory = binding.BuildChannelFactory<IRequestChannel>(
                parameters);
            channelFactory.Open();
            this.requestChannel = channelFactory.CreateChannel(remoteAddress);
        }
    
        public object Call(string op, string action, string[] varnames, object[] varvals, Type returntype)
        {
            requestChannel.Open(TimeSpan.MaxValue);
    
            //Message msg =
            //Message.CreateMessage(MessageVersion.<FromBinding>,
            //      action,
            //      new CustomBodyWriter(op, varnames, varvals,
            //"<ns passed in from Proxy>"));
    
            Message msg =                   
            Message.CreateMessage(this.messageVersion, action,
                  new CustomBodyWriter(op, varnames, varvals,               
            "<ns passed in from Proxy>"));
    
            Message reply = requestChannel.Request(msg, TimeSpan.MaxValue);
            XmlDictionaryReader reader = reply.GetReaderAtBodyContents();
            reader.ReadToFollowing(op + "Result");
            return reader.ReadElementContentAs(returntype, null);
        }
    
    }
    
    internal class CustomBodyWriter : BodyWriter
    {
        private string op;
        private string[] varnames;
        private object[] varvals;
        private string ns;
    
        public CustomBodyWriter(string op, string[] varnames, object[] varvals, string ns)
            : base(true)
        {
            this.op = op;
            this.varnames = varnames;
            this.varvals = varvals;
            this.ns = ns;
        }
    
        protected override void OnWriteBodyContents(XmlDictionaryWriter writer)
        {
            writer.WriteStartElement(op, ns);
            for (int i = 0; i < varnames.Length; i++)
                writer.WriteElementString(varnames[i], varvals[i].ToString());
            writer.WriteEndElement();
        }
    }
    
  9. Adicione as seguintes referências para ClientBase.cs:

  10. Adicione uma classe para instanciar e usar o proxy de cliente.

    O exemplo a seguir usa o objeto de vinculação para especificar a segurança de transporte HTTPS e o uso de um certificado de cliente para autenticação.Ele também mostra o código que invoca o proxy do cliente.

    Class Program
    
        ''' <summary>
        ''' The main entry point for the application.
        ''' </summary>
        <MTAThread()> _
        Shared Sub Main()
    
            Dim serverAddress As String = CalculatorServiceClient.ServiceEndPoint.Uri.AbsoluteUri
    
            Dim binding As New BasicHttpBinding()
    
            ' Specifies transport security over HTTPS and the use of a
            ' client certificate for authentication.
            binding.Security.Mode = BasicHttpSecurityMode.Transport
            binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Certificate
    
            Dim proxy = New CalculatorServiceClient(binding, New EndpointAddress(serverAddress))
    
            MessageBox.Show("Add 3 + 6...")
            MessageBox.Show(proxy.Add(3, 6).ToString())
            MessageBox.Show("Subtract 8 - 3...")
            MessageBox.Show(proxy.Subtract(8, 3).ToString())
    
        End Sub
    End Class
    
    static class Program
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [MTAThread]
    
        static void Main()
        {
            string serverAddress = CalculatorServiceClient.ServiceEndPoint.Uri.AbsoluteUri;
    
            BasicHttpBinding binding = new BasicHttpBinding();
    
            // Specifies transport security over HTTPS and the use of a
            // client certificate for authentication.
            binding.Security.Mode = BasicHttpSecurityMode.Transport;
            binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Certificate;
    
            ICalculatorService proxy = new CalculatorServiceClient(binding, new EndpointAddress(serverAddress));
    
            MessageBox.Show("Add 3 + 6...");
            MessageBox.Show((proxy.Add(3, 6)).ToString());
            MessageBox.Show("Subtract 8 - 3...");        
            MessageBox.Show((proxy.Subtract(8, 3)).ToString());
    
        }
    }
    
  11. Certifique-se de que o certificado de cliente foi colocado no armazenamento de certificados do usuário corrente do dispositivo.

  12. Construir o aplicativo cliente e implantá-lo em seu dispositivo.

  13. Quando o serviço WCF está sendo executado e o dispositivo está conectado à rede, inicie o aplicativo cliente no dispositivo.

Compilando o código

O código-fonte para o serviço do WCF requer referências aos namespaces seguintes:

O código-fonte para o ClientBase classe requer referências aos namespaces seguintes:

O código-fonte para a classe que contém o Main método no aplicativo cliente requer referências aos namespaces seguintes:

Segurança

Este exemplo implementa a segurança de transporte com base na autenticação mútua.Ele não implementa a segurança de mensagem.

Consulte também

Outros recursos

Desenvolvimento do Windows Communication Foundation (WCF) e o .NET Compact estrutura