He estado en todas partes de la red para esto. Lo he estado haciendo diablos, y el proveedor cuyo servicio web estoy tratando de consumir se niega a dar soporte oficialmente a WCF como método de consumo.(Intentando) migrar de WSE 3.0 a WCF para el código de cliente
No soy un experto en servicios web, por lo que haré todo lo posible para documentar y explicar esta publicación inicial, pero, por supuesto, solicito más información si la necesita, y espero que pueda proporcionarla. lo que sea necesario
El servicio
En mi empresa, se utiliza una aplicación de un proveedor que expone un servicio. La aplicación está escrita en Java, y parece que el wsdl se creó con Apache Axis 1.2.
El código
Mi código heredado utiliza WSE 3.0. En particular, utiliza las clases proxy que tienen "WSE" tachado automáticamente al final. Esto me permite usar un esquema de autenticación mucho más simple (la única forma en que podría hacerlo funcionar). No necesito usar certificados. Yo uso un derivado de SecurityPolicyAssertion
, y lo envuelvo en un objeto Policy
que se pasa al método SetPolicy
de la clase de cliente. Esto es todo lo que necesito hacer para crear una instancia de trabajo del cliente:
MyWebServiceWse api = new MyWebServiceWse();
api.Url = myUrl;
api.SetPolicy(new Policy(new MyDerivedSecurityAssertion(user, pass)));
Mi defecto, fuera de la caja de código para WCF (generado con una referencia de servicio) no acepta las credenciales, por lo que sé hay un problema desde el principio. He leído varias cosas en línea sobre el uso de diferentes security
o configuraciones de enlace en mi app.config
, pero nada ha funcionado por completo. Mi error más común después de retoques copiosos es WSDoAllReceiver: Request does not contain required Security header
.
Aquí está la aplicación.config. Tal vez podríamos empezar diciéndome qué debería cambiar aquí para facilitar el paso de las credenciales; una vez más, he visto diversas opiniones en línea.
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="MySoapBinding" closeTimeout="00:01:00"
openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
maxBufferSize="65536" maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered"
useDefaultWebProxy="true">
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<security mode="None">
<transport clientCredentialType="None" proxyCredentialType="None"
realm="" />
<message clientCredentialType="UserName" algorithmSuite="Default" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint address="http://xyz:12345/services/MyService"
binding="basicHttpBinding" bindingConfiguration="MySoapBinding"
contract="MyNS.MyService" name="MyService" />
</client>
</system.serviceModel>
</configuration>
He cambiado algunos de los atributos para ocultar el servicio específico que estamos utilizando (política de la compañía y todo eso).
Y aquí es el código de ejemplo de C# hasta el momento (prueba en una aplicación de consola):
MyClient client = new MyClient();
client.listMethod();
ACTUALIZACIÓN
Leer este SO mensaje: wcf security . . ..
He actualizado mi app.config en consecuencia, y ahora estoy pasando el nombre de usuario y pwd en el código. Todavía estoy recibiendo el mismo error:
WSDoAllReceiver: Request does not contain required Security header
20120517 ACTUALIZACIÓN
Una solicitud exitosa (de WSE3):
<soap:Header>
<wsa:Action>
</wsa:Action>
<wsa:MessageID>urn:uuid:cb739422-c077-4eec-8cb2-686837b76878</wsa:MessageID>
<wsa:ReplyTo>
<wsa:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:Address>
</wsa:ReplyTo>
<wsa:To>http://removed-for-security</wsa:To>
<wsse:Security soap:mustUnderstand="1">
<wsu:Timestamp wsu:Id="Timestamp-e13feaf9-33d9-47bf-ab5b-60b4611eb81a">
<wsu:Created>2012-05-17T11:25:41Z</wsu:Created>
<wsu:Expires>2012-05-17T11:30:41Z</wsu:Expires>
</wsu:Timestamp>
<wsse:UsernameToken xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="SecurityToken-00c26e1a-3b3b-400f-a99a-3aa54cf8c8ff">
<wsse:Username>change-to-protect-the-innocent</wsse:Username>
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">nice-try</wsse:Password>
<wsse:Nonce>KJMvUuWF2eO2uIJCuxJC4A==</wsse:Nonce>
<wsu:Created>2012-05-17T11:25:41Z</wsu:Created>
</wsse:UsernameToken>
</wsse:Security>
</soap:Header>
<soap:Body>
<listChannels xmlns="http://removed-for-security">
<rowfrom>0</rowfrom>
<rowto>10</rowto>
</listChannels>
</soap:Body>
</soap:Envelope>
trabajando en conseguir la trazabilidad de WCF -Me agregaré en breve.
20120517 ACTUALIZACIÓN 2
Y aquí está el sobre de WCF:
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Header>
<Action s:mustUnderstand="1" xmlns="http://schemas.microsoft.com/ws/2005/05/addressing/none"></Action>
</s:Header>
<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<listChannels xmlns="http://removed-for-security">
<rowfrom>1</rowfrom>
<rowto>2147483647</rowto>
</listChannels>
</s:Body>
</s:Envelope>
20120518 ACTUALIZACIÓN He tratado de implementar la solución en el post que Mike Miller une a en los comentarios. Ahora recibo el siguiente error (sin mensaje termina siendo enviado porque barfing de algo en el esquema):
The provided URI scheme 'http' is invalid; expected 'https'.
Y por si alguien quiere preguntar, sí, tengo que enviar a través de http, y sí, me m consciente de que las credenciales se envían como cadenas sin encriptar :-)
Lo primero que compararía son las solicitudes de jabón generadas por los clientes de WSE y WCF. Dado que el cliente WCF está configurado para 'security mode = 'None' 'probablemente no se está creando un encabezado de seguridad soap, pero las solicitudes capturadas lo mostrarán. Creo que el basicHttpBinding no se puede configurar para admitir la seguridad del nivel de mensajes. Es probable que necesite el wsHttpBinding para esa configuración. Por último, observe lo que Microsoft ha hecho en el proyecto [WCF Express Interop] (http://wcf.codeplex.com/wikipage?title=WCF%20Express%20Interop%20Bindings), sus asistentes también se pueden aplicar a los clientes de WCF. –
Gracias, Sixto: ¿cuál es la mejor manera de capturar la solicitud que está enviando WCF? –
WCF tiene una característica incorporada [seguimiento de mensajes] (http://msdn.microsoft.com/en-us/library/ms730064.aspx) pero también puede usar [Fiddler] (http: //www.fiddler2. com/fiddler2 /) para capturar el tráfico de los clientes WSE y WCF. Para ampliar mi comentario anterior, debe enfocarse en crear su nuevo cliente WCF desde el punto de vista de la interfaz con un servicio Apache Axis en lugar de hacerlo desde un cliente WSE heredado. A pesar de la promesa de "interoperabilidad" de los estándares WS- *, es realmente doloroso conseguir que WCF trabaje con cualquier servicio o cliente que no esté basado en WCF. –