Aplicación de C# XMLRPC.NET cliente y el servidor a través de HTTPS

Es bastante difícil encontrar información acerca de XMLRPC.net la biblioteca utiliza con https.

La única documentación, donde un «https» en la dirección URL se puede establecer es de aquí : http://xml-rpc.net/faq/xmlrpcnetfaq-2-5-0.html#2.3, pero sin embargo, no explica exactamente cómo puede una instalación correctamente.

Experimentando sobre la base de los ejemplos proporcionados en las descargas http://xmlrpcnet.googlecode.com/files/xml-rpc.net.2.5.0.zip he intentado esto :

Cambios en el cliente.cs archivo de StateNameServer solución :

IStateName svr = (IStateName)Activator.GetObject(
typeof(IStateName), "https://localhost:5678/statename.rem");

Lo que el código del servidor parece

    IDictionary props = new Hashtable();
    props["name"] = "MyHttpChannel";
    props["port"] = 5678;
    HttpChannel channel = new HttpChannel(
    props,
    null,
    new XmlRpcServerFormatterSinkProvider()
    );

    ChannelServices.RegisterChannel(channel, false);

    RemotingConfiguration.RegisterWellKnownServiceType(
    typeof(StateNameServer),
    "statename.rem",
    WellKnownObjectMode.Singleton);

El cliente obviamente gotas de una excepción al intentar comunicarse con el servidor mediante HTTPS, porque no sé cómo configurarlo. Podría alguien ayudar, de todos modos, por favor ? ¿Qué tipo de cosas que debo buscar ?

Muchas gracias !

OriginalEl autor virrea | 2011-10-26

3 Kommentare

  1. 3

    Primer lugar, me gustaría agradecer calurosamente a Charles Cook, por su ayuda en este problema y para el desarrollo de XMLRPC.NET.

    Segundo, en este ejemplo se basa en el XMLRPC.NET StateNameServer muestra disponible para descargar aquí :
    http://xml-rpc.net/download.html

    Así que aquí está la solución :

    1. Generar o conseguir un [auto-firmado] certificado (con makecert.exe por ejemplo)

    2. Agregar este certificado para el servidor de configuración y especifique el puerto que desea usar con su XMLRPC.NET servidor (en este caso 5678) el uso de httpcfg.exe o de otra herramienta como HttpSysConfig (Open Source)

    3. Implementar su XMLRPC.NET servidor utilizando el siguiente código :

    using System;
    using System.Collections;
    using System.Runtime.Remoting;
    using System.Runtime.Remoting.Channels;
    using System.Runtime.Remoting.Channels.Http;
    
    using CookComputing.XmlRpc;
    
    using System.Net;
    using System.IO;
    
    public class _
    {
        static void Main(string[] args)
        {
            HttpListener listener = new HttpListener();
            listener.Prefixes.Add("https://127.0.0.1:5678/");
            listener.Start();
            while (true)
            {
                HttpListenerContext context = listener.GetContext();
                ListenerService svc = new StateNameService();
                svc.ProcessRequest(context);
            }
    
            Console.WriteLine("Press <ENTER> to shutdown");
            Console.ReadLine();
        }
    }
    
    public class StateNameService : ListenerService
    {
        [XmlRpcMethod("examples.getStateName")]
        public string GetStateName(int stateNumber)
        {
            if (stateNumber < 1 || stateNumber > m_stateNames.Length)
                throw new XmlRpcFaultException(1, "Invalid state number");
            return m_stateNames[stateNumber - 1];
        }
    
        string[] m_stateNames
          = { "Alabama", "Alaska", "Arizona", "Arkansas",
            "California", "Colorado", "Connecticut", "Delaware", "Florida",
            "Georgia", "Hawaii", "Idaho", "Illinois", "Indiana", "Iowa", 
            "Kansas", "Kentucky", "Lousiana", "Maine", "Maryland", "Massachusetts",
            "Michigan", "Minnesota", "Mississipi", "Missouri", "Montana",
            "Nebraska", "Nevada", "New Hampshire", "New Jersey", "New Mexico", 
            "New York", "North Carolina", "North Dakota", "Ohio", "Oklahoma",
            "Oregon", "Pennsylviania", "Rhose Island", "South Carolina", 
            "South Dakota", "Tennessee", "Texas", "Utah", "Vermont", "Virginia", 
            "Washington", "West Virginia", "Wisconsin", "Wyoming" };
    }
    
    public abstract class ListenerService : XmlRpcHttpServerProtocol
    {
        public virtual void ProcessRequest(HttpListenerContext RequestContext)
        {
            try
            {
                IHttpRequest req = new ListenerRequest(RequestContext.Request);
                IHttpResponse resp = new ListenerResponse(RequestContext.Response);
                HandleHttpRequest(req, resp);
                RequestContext.Response.OutputStream.Close();
            }
            catch (Exception ex)
            {
                //"Internal server error"
                RequestContext.Response.StatusCode = 500;
                RequestContext.Response.StatusDescription = ex.Message;
            }
        }
    }
    
    public class ListenerRequest : CookComputing.XmlRpc.IHttpRequest
    {
        public ListenerRequest(HttpListenerRequest request)
        {
            this.request = request;
        }
    
        public Stream InputStream
        {
            get { return request.InputStream; }
        }
    
        public string HttpMethod
        {
            get { return request.HttpMethod; }
        }
    
        private HttpListenerRequest request;
    }
    
    public class ListenerResponse : CookComputing.XmlRpc.IHttpResponse
    {
        public ListenerResponse(HttpListenerResponse response)
        {
            this.response = response;
        }
    
        string IHttpResponse.ContentType
        {
            get { return response.ContentType; }
            set { response.ContentType = value; }
        }
    
        TextWriter IHttpResponse.Output
        {
            get { return new StreamWriter(response.OutputStream); }
        }
    
        Stream IHttpResponse.OutputStream
        {
            get { return response.OutputStream; }
        }
    
        int IHttpResponse.StatusCode
        {
            get { return response.StatusCode; }
            set { response.StatusCode = value; }
        }
    
        string IHttpResponse.StatusDescription
        {
            get { return response.StatusDescription; }
            set { response.StatusDescription = value; }
        }
    
        private HttpListenerResponse response;
    }
    
    public class StateNameServer : MarshalByRefObject, IStateName
    {
      public string GetStateName(int stateNumber)
      {
        if (stateNumber < 1 || stateNumber > m_stateNames.Length)
          throw new XmlRpcFaultException(1, "Invalid state number");
        return m_stateNames[stateNumber-1]; 
      }
    
      public string GetStateNames(StateStructRequest request)
      {
        if (request.state1 < 1 || request.state1 > m_stateNames.Length)
          throw new XmlRpcFaultException(1, "State number 1 invalid");
        if (request.state2 < 1 || request.state2 > m_stateNames.Length)
          throw new XmlRpcFaultException(1, "State number 1 invalid");
        if (request.state3 < 1 || request.state3 > m_stateNames.Length)
          throw new XmlRpcFaultException(1, "State number 1 invalid");
        string ret = m_stateNames[request.state1-1] + " "
          + m_stateNames[request.state2-1] + " " 
          + m_stateNames[request.state3-1];
        return ret;
      }
    
      string[] m_stateNames 
        = { "Alabama", "Alaska", "Arizona", "Arkansas",
            "California", "Colorado", "Connecticut", "Delaware", "Florida",
            "Georgia", "Hawaii", "Idaho", "Illinois", "Indiana", "Iowa", 
            "Kansas", "Kentucky", "Lousiana", "Maine", "Maryland", "Massachusetts",
            "Michigan", "Minnesota", "Mississipi", "Missouri", "Montana",
            "Nebraska", "Nevada", "New Hampshire", "New Jersey", "New Mexico", 
            "New York", "North Carolina", "North Dakota", "Ohio", "Oklahoma",
            "Oregon", "Pennsylviania", "Rhose Island", "South Carolina", 
            "South Dakota", "Tennessee", "Texas", "Utah", "Vermont", "Virginia", 
            "Washington", "West Virginia", "Wisconsin", "Wyoming" };
    }

    4. Implementar su XMLRPC.NET cliente usando el siguiente código (el código también se crea un nuevo X509 certificado de cliente)

    using System;
    using System.Collections;
    using System.Runtime.Remoting;
    using System.Runtime.Remoting.Channels;
    using System.Runtime.Remoting.Channels.Http;
    
    using CookComputing.XmlRpc;
    using System.Net;
    using System.Security.Cryptography.X509Certificates;
    
    class _
    {
        public class TrustAllCertificatePolicy : System.Net.ICertificatePolicy
        {
            public TrustAllCertificatePolicy() { }
            public bool CheckValidationResult(ServicePoint sp,
               X509Certificate cert,
               WebRequest req,
               int problem)
            {
                return true;
            }
        }
        static void Main(string[] args)
        {
            System.Net.ServicePointManager.CertificatePolicy = new TrustAllCertificatePolicy();
            IStateName proxy = XmlRpcProxyGen.Create<IStateName>();
            XmlRpcClientProtocol cp = (XmlRpcClientProtocol)proxy;
            cp.Url = "https://127.0.0.1:5678/";
            cp.ClientCertificates.Add(new System.Security.Cryptography.X509Certificates.X509Certificate(@"C:\path\to\your\certificate\file\my.cer"));
            cp.KeepAlive = false;
            //cp.Expect100Continue = false;
            //cp.NonStandard = XmlRpcNonStandard.All;
    
            string stateName = ((IStateName)cp).GetStateName(13);
        }
    }

    Por supuesto, yo no doy aquí la implementación de la interfaz para el ServerStateName pero usted encontrará en los archivos de la muestra utilizando el enlace de descarga en la parte superior.

    Comentario :

    System.Net.ServicePointManager.CertificatePolicy = new TrustAllCertificatePolicy(); permitirá la implementación del servidor para aceptar el certificado auto-firmado generado por ti mismo. Creo que esto no es necesario con los certificados emitidos por autoridades de certificación.

    Si usted encuentra cualquier cosa que podría ser mejorado y es incorrecto que será muy apreciada.

    Después de las pruebas, puedo confirmar que la aplicación funciona en dos Ventanas distintas máquinas.

    OriginalEl autor virrea

  2. 2

    Crear un proxy de cliente utilizando XmlRpcProxyGen.Crear, especificando la dirección url https (su interfaz debe derivar de IXmlRpcProxy). Si usted necesita para suministrar certificado de cliente(s) que el proxy tiene una propiedad ClientCertificates que puede ser utilizado de la misma manera que la propiedad correspondiente en el Sistema.Net.Clase HttpWebRequest.

    No creo que Remoting puede apoyar HTTPS. Usted puede utilizar HttpListener como se describe en el XML-RPC.NET PREGUNTAS FRECUENTES pero usted tendrá que configurar un certificado, por ejemplo, como se describe en este blog

    Gracias Carlos. He intentado utilizar XmlRpcProxyGen pero el cliente sigue bajando excepción al intentar enviar los datos. No el servidor necesita algún tipo de certificado ?
    Se añadió el párrafo sobre la implementación de un servidor.
    Gracias por tu ayuda Carlos, tu enlace me ayudó a encontrar la solución. He añadido el certificado para el servidor (mi equipo local, de hecho)… el resto de la solución a continuación en mi respuesta.

    OriginalEl autor Charles Cook

  3. 1

    Gran artículo! Me ayuda mucho.
    Pero el punto 1 y 2 me llevó un día a la figura. Así que aquí va mi experiencia:

    1. Para generar un certificado autofirmado he utilizado openssl herramienta. Simplemente siga las instrucciones en el enlace. Este certificado lo necesario para la aplicación de cliente.
    2. Para la aplicación de servidor que necesitaba otro certificado. Código de servidor utiliza HttpListener clase que no tiene Certificados de propiedad. No hay ninguna manera de cómo aplicar certificado específico a instancia de HttpListener clase. Hay otra estrategia:
      • Crear un nuevo certificado en el certificado local de almacenamiento.
        Para hacer este tipo de ‘mmc’ cmd->Archivo->Agregar o Quitar Complemento-en->Certificados->Agregar->cuenta de Equipo->equipo Local->OK. Ir a Personal->Certificados->click Derecho->Todas las tareas->Solicitar un nuevo certificado. Siguiente>Siguiente>seleccione Servidor Web->haga clic en el enlace azul->básicamente, usted necesita para sentirse solo Nombre Común aquí (poner deseada nombre del certificado). Ok->Inscribir. Ahora usted tiene la suya certificado en el local de almacenamiento.
      • Enlazar certificado creado específicos ip/puerto de par.
        Para ello ejecute la siguiente cadena en el cmd: netsh http add sslcert ipport=192.168.111.195:4022 certhash=c8973a86141a7a564a6f509d1ecfea326a1852a2 appid={0a582a74-fc2d-476c-9281-c73b2e4bfb26}, donde ‘ipport’ es par de ip/puerto que será utilizado para la conexión ssl; ‘certhash’ es un hash del certificado (abrir certificado que creó en el paso anterior->ir a los Detalles->buscar Huella digital); ‘appid» podría ser cualquiera.

    Si se especifica ‘https’ en su HttpListener url de esta clase buscará automáticamente encuadernada de certificados.

    Glat ayudó ! 🙂 Voy a tener un intento a las notas.

    OriginalEl autor Vladyslav Chernysh

Kommentieren Sie den Artikel

Bitte geben Sie Ihren Kommentar ein!
Bitte geben Sie hier Ihren Namen ein

Pruebas en línea