2009-05-12 55 views
12

Así que tengo una ServiceReference añadida a una aplicación de consola C# que llama a un servicio web que está expuesto desde Oracle.¿Implementa un cliente C# que usa WebServices sobre SSL?

Tengo todo configurado y funciona como melocotones cuando no está usando SSL (http). Intento configurarlo utilizando SSL ahora, y estoy teniendo problemas para agregarlo a las Referencias de servicios (o incluso a las Referencias web). Por ejemplo, la URL (https) en la que se expone el servicio no devuelve los métodos web adecuados cuando intento agregarlos a Visual Studio.

La conexión subyacente se cerró: Se produjo un error inesperado en un envío. Recibió un EOF inesperado o 0 bytes de la secuencia de transporte. metadatos contiene una referencia que no pueda ser resuelto: 'https://srs204.mywebsite.ca:7776/SomeDirectory/MyWebService?WSDL'

Otro dilema que tengo es en lo que respecta a la gestión de certificados y el despliegue. Tengo alrededor de 1000 sitios de clientes externos que necesitarán usar esta pequeña utilidad y necesitarán que el certificado esté instalado en la tienda de certificados apropiada para poder conectarse al servicio web. No estoy seguro del mejor enfoque para manejar esto. ¿Deben estar en la tienda raíz?

He pasado bastantes horas en la web mirando varias opciones pero no puedo obtener una buena respuesta limpia en ninguna parte.

En resumen, tengo un par de preguntas aquí:

1) Alguien tiene algunos buenos enlaces en la creación de servicios web en Visual Studio que utilice SSL?

2) ¿Cómo debo registrar el certificado? ¿Qué tienda debería existir? ¿Puedo usar algo como CertMgr para registrarlo?

Tiene que haber un buen libro/tutorial/lo que sea que me muestre las buenas prácticas comunes para establecer algo como esto. ¡Parece que no puedo encontrarlo!

+0

¿Ha consultado con la persona que creó el sitio web para ver cómo está configurado en su extremo? –

+0

Están en el mismo edificio en este momento, así que si es algo relacionado con el servidor, puedo cambiarlo. Puedo desplegar la URL https en un navegador y me muestra la página de prueba estándar de Oracle Web Service. Entonces puedo golpearlo. Me pide aceptar un certificado cuando pulso esa URL. Me han proporcionado dos archivos .cer (uno para el servidor de desarrollo, uno para el servidor de producción) que deberán registrarse. –

+1

Si abre la url (https) en un navegador, ¿ve lo que espera? ¿Otros usuarios usan este servicio en https sin problema? No estoy seguro de cómo funcionan los servicios web Oracle, pero si está alojado en oa través de IIS, deberá agregar el nombre de dominio (webservice.servicehost.com) como un encabezado de host SSL. – Nate

Respuesta

28

Bueno, lo he descubierto. Me llevó mucho más tiempo de lo que me gustaría hablar, pero quería compartir mi solución, ya que es una GRAN molestia para mí ver el estándar. "¡Lo arreglé! ¡Gracias!" publicaciones que dejan a todos pendientes de lo que realmente sucedió.

So.

El problema principal era que, de forma predeterminada, Visual Studio 2008 usa TLS para el protocolo de enlace SSL y el servicio web basado en Oracle/Java al que estaba intentando conectar estaba usando SSL3.

Cuando utiliza la "Agregar referencia de servicio ..." en Visual Studio 2008, tiene no way to specify that the security protocol para el administrador del punto de servicio debe ser SSL3.

A menos que.

Toma un documento WSDL estático y use wsdl.exe to generate a proxy class.

wsdl /l:CS /protocol:SOAP /namespace:MyNamespace MyWebService.wsdl 

continuación, puede utilizar la C Sharp Compiler de convertir esa clase de proxy en una biblioteca (DLL) y añadirlo a sus proyectos .Net "Referencias".

csc /t:library /r:System.Web.Services.dll /r:System.Xml.dll MyWebService.cs 

En este punto también hay que asegurarse de que usted ha incluido en sus System.Web.Services "Referencias" también.

Ahora debería poder llamar a su servicio web sin problemas en el código. Para que sea trabajo va a necesitar una línea mágica de código agregado antes de crear una instancia del servicio.

// We're using SSL here and not TLS. Without this line, nothing workie. 
ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3; 

Bien, entonces me sentía bastante impresionado conmigo mismo, ya que las pruebas eran geniales en mi caja de desarrollo. Luego implementé en otro cuadro de cliente y no se volvería a conectar debido a un problema de permisos/autoridad. Esto olía a certificados para mí (como huelen). Para resolver esto, I used certmgr.exe para registrar el certificado del sitio en la raíz de confianza en la máquina local.

certmgr -add -c "c:\someDir\yourCert.cer" -s -r localMachine root 

Esto me permite distribuir el certificado a nuestros sitios de clientes e instalarlo automáticamente para los usuarios. Todavía no estoy seguro de cuán "amigables para la seguridad" tendrán las diferentes versiones de Windows con respecto a los registros automáticos de certificados como este, pero hasta ahora ha funcionado muy bien.

Espero que esta respuesta ayude a algunas personas. Gracias a blowdart también por toda su ayuda en este caso y brindando algunas ideas.

+1

Siempre responda sus propias preguntas si se le ocurre. Me has salvado señor. (Tuve un servidor web anunciando que TLS era compatible. ¡Descubrí que no lo era!) – DFTR

+0

Solo estaba navegando SO. Realmente no tenía una pregunta sobre esto, pero estaba muy contento de ver su resolución. Parecía que requirió mucha investigación. Gran explicación! ¡Gracias! – jason

+0

¡Muy contento de escuchar que ayudé a alguien y con suerte salvé un poco de dolor! :) –

4

Parece que el servicio web está utilizando un certificado autofirmado. Francamente, este no es el mejor enfoque.

Asumiendo que usted es una organización grande y es interna, puede configurar su propia autoridad de certificación confiable, esto es especialmente fácil con Active Directory. Desde esa CA, el servidor que aloja el servicio de Oracle podría solicitar un certificado y usted puede usar la política de AD para confiar en el certificado raíz de su CA interna colocándolo en la raíz de confianza del almacén de máquinas. Esto eliminaría la necesidad de confiar o aceptar manualmente el certificado en el servicio web.

Si las máquinas del cliente son externas, tendrá que conseguir que la gente que expone el servicio compre un certificado "real" de una de las conocidas CA como Verisign, Thawte, GeoTrust, etc. o como parte de su instalación agrupe el certificado público e instálelo en las autoridades de certificación de raíz de confianza en el nivel de la máquina en cada máquina. Esto tiene problemas, por ejemplo, no hay forma de revocar el certificado, pero eliminará el aviso.

+0

¡Gracias por la respuesta! Me han proporcionado dos certificados. Uno para el servidor de "desarrollo" y otro para el servidor de "producción". Nuestros sitios de clientes son externos, así que tendré que preocuparme de registrarlos manualmente. ¿Algún buen enlace sobre la mejor manera de introducirlos en la tienda de máquinas raíz de confianza? El certificado de producción es de GTE CyberTrust y es un certificado de raíz global que cubre todas las políticas de emisión y todas las políticas de aplicación. –

+1

Así que no tendrá que preocuparse por el servidor en vivo, funcionará de inmediato ya que GTE es una raíz de confianza (creo que está un poco confundido; es poco probable que el servidor en vivo tenga su propio certificado de root, es probablemente solo un certificado normal). Para comprobar, agregaría una referencia al servicio en vivo y veré qué sucede. Si todo está bien, entonces para el desarrollador solo necesita instalar el certificado en su máquina. Inicie MMC y agregue el complemento de cerificates, diciéndole que use la máquina local. A continuación, importe el certificado dev en la raíz de confianza. – blowdart

+0

Gotcha. He ejecutado MMC, he utilizado el complemento de certificados para asegurarme de que la autoridad de certificaciones de desarrollo se haya agregado a la "raíz de confianza" para la computadora local. Todavía no se puede conectar a la versión de desarrollo del servicio. No puedo probar contra la versión de producción porque aún no estamos fuera de desarrollo. Sin embargo, podría ser capaz de hacer que traten de arreglarme algo. ¿Existe alguna posibilidad de que algo pueda estar mal con el certificado de desarrollo? Si tengo el certificado correcto instalado en mi sistema, debería poder agregar la referencia del servicio HTTPS sin un error, ¿verdad? –

1

Mat,

que tenía tales problemas también y tienen una forma de evitar el uso de Certmgr.exe añadir certificados a raíz de confianza en una máquina remota.

X509Store store; 
store = new X509Store("ROOT", StoreLocation.LocalMachine); 
store.Open(OpenFlags.ReadWrite); 
store.Add(certificate); 

El 'objeto de certificado' se pueden crear de esta manera:

X509Certificate2 certificate = new X509Certificate2("Give certificate location path here"); 
+0

¡Hola, gracias por la respuesta! Ya hemos implementado en nuestros sitios de clientes una secuencia de comandos personalizada que está utilizando certmgr.exe pero me gusta mucho más esta solución. Lo probaremos cuando profundicemos en ese código la próxima vez que haya un cambio. –

1

Gracias por este gran consejo, tomó un vistazo a su alrededor en su materia y usted tiene un montón de buenas ideas pasando. Esto es lo que tengo que añadir: estoy averiguando webMethods y (¡sorpresa!) Tiene los mismos problemas que el servidor de la aplicación Oracle al que te conectaste (SSL3 en lugar de TLS). Tu enfoque funcionó muy bien, aquí está mi apéndice.

Dada clase estática "de fábrica" ​​proveer estos dos elementos práctico-excelente:

/// <summary> 
/// Used when dispatching code from the Factory (for example, SSL3 calls) 
/// </summary> 
/// <param name="flag">Make this guy have values for debugging support</param> 
public delegate void CodeDispatcher(ref string flag); 

/// <summary> 
/// Run code in SSL3 -- this is not thread safe. All connections executed while this 
/// context is active are set with this flag. Need to research how to avoid this... 
/// </summary> 
/// <param name="flag">Debugging context on exception</param> 
/// <param name="dispatcher">Dispatching code</param> 
public static void DispatchInSsl3(ref string flag, CodeDispatcher dispatcher) 
{ 
    var resetServicePoint = false; 
    var origSecurityProtocol = System.Net.ServicePointManager.SecurityProtocol; 
    try 
    { 
    System.Net.ServicePointManager.SecurityProtocol = System.Net.SecurityProtocolType.Ssl3; 
    resetServicePoint = true; 
    dispatcher(ref flag); 
    } 
    finally 
    { 
    if (resetServicePoint) 
    { 
     try { System.Net.ServicePointManager.SecurityProtocol = origSecurityProtocol; } 
     catch { } 
    } 
    } 
} 

Y después de consumir estas cosas (como sin duda habrá adivinado ya, pero poner un redoble de tambor aquí de todos modos) :

var readings = new ArchG2.Portal.wmArchG201_Svc_fireWmdReading.wmdReading[] { 
     new ArchG2.Portal.wmArchG201_Svc_fireWmdReading.wmdReading() { 
     attrID = 1, created = DateTime.Now.AddDays(-1), reading = 17.34, userID = 2 
     }, 
     new ArchG2.Portal.wmArchG201_Svc_fireWmdReading.wmdReading() { 
     attrID = 2, created = DateTime.Now.AddDays(-2), reading = 99.76, userID = 3 
     }, 
     new ArchG2.Portal.wmArchG201_Svc_fireWmdReading.wmdReading() { 
     attrID = 3, created = DateTime.Now.AddDays(-5), reading = 82.17, userID = 4 
     } 
    }; 
    ArchG2.Portal.Utils.wmArchG201.Factory.DispatchInSsl3(ref flag, (ref string flag_inner) => 
    { 
     // creates the binding, endpoint, etc. programatically to avoid mucking with 
     // SharePoint web.config. 
     var wsFireWmdReading = ArchG2.Portal.Utils.wmArchG201.Factory.Get_fireWmdReading(ref flag_inner, LH, Context); 
     wsFireWmdReading.fireWmdReading(readings); 
    }); 

Que hace el truco - cuando tenga más tiempo voy a resolver el problema de enhebrado (o no).

+0

+1 - Impresionante. A veces, estos tipos de errores oscuros y correcciones son difíciles de encontrar. ¡Gracias por publicar y felicitaciones! –

1

Como no tengo la reputación de comentar, me gustaría mencionar que la respuesta y el código de ejemplo de Mat Nadrofsky para forzar SSL3 es también la solución para un error similar al

producido un error al hacer el Solicitud de HTTP al https://xxxx/whatever. Esto podría deberse al hecho de que el certificado del servidor no está configurado correctamente con HTTP.SYS en el caso de HTTPS . Esto también podría deberse a una falta de coincidencia del enlace de seguridad entre el cliente y el servidor.

sólo tiene que utilizar

// We're using SSL here and not TLS. Without this line, nothing workie. 
ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3; 

como se ha mencionado por Mat. Probado con un servidor SAP NetWeaver PI en HTTPS. ¡Gracias!

+0

¡Hola, gracias por publicar y me alegro de poder ayudar! :) –

Cuestiones relacionadas