2008-08-19 14 views
21

Necesito llamar a un servicio web escrito en .NET desde Java. El servicio web implementa la pila WS-Security (ya sea WSE 2 o WSE 3, no está claro a partir de la información que tengo).Llamar al servicio web .NET (WSE 2/3, WS-Security) desde Java

La información que recibí del proveedor de servicios incluía WSDL, un archivo policyCache.config, algunos ejemplos de código C# y una aplicación de muestra que puede llamar al servicio con éxito.

Esto no es tan útil como parece porque no está claro cómo se supone que debo usar esta información para escribir un cliente Java. Si la solicitud del servicio web no está firmada según la política, el servicio la rechaza. Intento usar Apache Axis2 y no encuentro instrucciones sobre cómo se supone que debo usar el archivo policyCahce.config y el WSDL para generar un cliente.

Hay varios ejemplos que he encontrado en la Web, pero en todos los casos los autores de los ejemplos tenían control tanto del servicio como del cliente y por lo tanto podían hacer ajustes en ambos lados para que funcionara . No estoy en esa posición.

¿Alguien ha hecho esto con éxito?

+0

WSE es obsoleto, y solo debe usarse si no hay otras opciones. –

+0

@Michael: amigo, siento tu dolor (ya que mi búsqueda HOWTO me llevó aquí). – Roboprog

Respuesta

9

Esta parece ser una pregunta popular, así que proporcionaré una visión general de lo que hicimos en nuestra situación.

Parece que los servicios incorporados en .NET siguen un estándar anterior de direccionamiento ws (http://schemas.xmlsoap.org/ws/2004/03/addressing/) y axis2 solo entiende el estándar más reciente (http://schemas.xmlsoap.org/ws/2004/08/addressing/).

Además, el archivo policyCache.config proporcionado está en una forma que el módulo de eje de axis2 no puede entender.

Así que los pasos que tenía que hacer, en pocas palabras:

  • Leer el policyCache.config y tratar de entenderlo. Luego reescríbalo en una política que terraplén podría entender. (Unas updated docs ayudaron.)
  • Configure el terraplén con esta política.
  • Tome las claves que se proporcionan en el archivo .pfx y conviértalos a un almacén de claves java. Hay una utilidad que viene con Jetty que puede hacer eso.
  • Configure el terraplén con ese almacén de claves.
  • Escriba un controlador axis2 personalizado que convierta las últimas novedades de ws-addresses que salen de axis2 en las cosas más antiguas que espera el servicio.
  • Configure axis2 para usar el controlador en los mensajes salientes.

Al final hubo mucha configuración y código para algo que se supone que es un estándar abierto compatible con los proveedores.

Aunque no estoy seguro de cuál es la alternativa ... ¿puede esperar a los proveedores (o en este caso, el único proveedor) para asegurarse de que todo sea interoperativo?

Como postdata añadiré que no terminé haciendo el trabajo, era alguien más en mi equipo, pero creo que obtuve los detalles más importantes correctos. La otra opción que estaba considerando (antes de que mi compañero de equipo asumiera el control) era llamar directamente a la API WSS4J para construir el sobre SOAP, como lo esperaba el servicio .NET. Creo que eso también hubiera funcionado.

+0

Este problema de direccionamiento ws es un verdadero dolor en el culo. WSS2 no solo usa una versión anterior de WS-Addressing, sino que agrega elementos propritery al encabezado soap (por ejemplo, wsa: via) que no forman parte del esquema. Qué ganga. – skaffman

+2

Todos deben tener en cuenta que WSE está obsoleto. Era una solución provisional para permitir que los servicios web de .NET utilizaran la pila WS- * emergente. No debería sorprender que no sea compatible con los estándares finales. WCF _does_ admite las versiones estándares finales de los protocolos WS- *. Ha reemplazado a WSE y debería usarse para todo nuevo desarrollo. El código de WSE debe reemplazarse lo antes posible. –

+1

@John: las personas que implementan un cliente no tienen muchas opciones que el proveedor usó para implementar el servidor. Veo que te ganas la vida haciendo estas cosas, pero para los desarrolladores que tienen que integrarse con estas cosas, realmente apesta que sea * tan * dependiente de tener las herramientas correctas de la versión correcta de One True Vendor. Consulte http://72.249.21.88/nonintersecting/?year=2006&monthnum=11&day=15&name=the-s-stands-for-simple&page – Roboprog

0

CXF - Miraría en CXF. Lo he usado para crear un servicio web y un cliente en Java usando ws-secuirty. También conecté un servicio web .net.

También tienen una documentación bastante buena. Tuve más suerte con eso que con el eje.

0

Supongo que debería ser más claro: he usado los generadores de código wsdl2java para generar código de cliente para el servicio. Sin embargo, el código generado no incluye los encabezados SOAP WS-Security necesarios para que el servicio acepte las solicitudes.

+0

¿Lo resolvió? Me enfrento con una tarea similar y todavía tengo que hacer que todas las piezas funcionen con un solo framework (puedo usar CXF pero tengo problemas con SSL, tengo problemas con las configuraciones de Rampart). Parece que la mayoría de los ejemplos tienen control sobre el cliente y el servidor. –

+0

@aurealus - Sí, lo hicimos, actualizó esta pregunta. Espero que te ayude. :) –

2

@ Mike

poco hice una prueba y este es el código que he usado. No uso políticas, pero usé WS-Security con autenticación de texto plano. CXF tiene muy buena documentación sobre cómo lograr esto.

Utilicé wsdl2java y luego agregué este código para usar el servicio web con ws-security.

Espero que esto te ayude.

import java.io.IOException; 
import java.util.HashMap; 
import java.util.Map; 

import javax.security.auth.callback.Callback; 
import javax.security.auth.callback.CallbackHandler; 
import javax.security.auth.callback.UnsupportedCallbackException; 

import org.apache.cxf.ws.security.wss4j.WSS4JOutInterceptor; 
import org.apache.ws.security.WSConstants; 
import org.apache.ws.security.WSPasswordCallback; 
import org.apache.ws.security.handler.WSHandlerConstants; 

public class ServiceTest implements CallbackHandler 
{ 

    public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException { 

      WSPasswordCallback pc = (WSPasswordCallback) callbacks[0]; 
      // set the password for our message. 
      pc.setPassword("buddah"); 
     } 

    public static void main(String[] args){ 
     PatientServiceImplService locator = new PatientServiceImplService(); 
     PatientService service = locator.getPatientServiceImplPort(); 

     org.apache.cxf.endpoint.Client client = org.apache.cxf.frontend.ClientProxy.getClient(service); 
     org.apache.cxf.endpoint.Endpoint cxfEndpoint = client.getEndpoint(); 

     Map<String, Object> outProps = new HashMap<String, Object>(); 
     outProps.put(WSHandlerConstants.ACTION, WSHandlerConstants.USERNAME_TOKEN + " " + WSHandlerConstants.TIMESTAMP); 
     outProps.put(WSHandlerConstants.USER, "joe"); 
     outProps.put(WSHandlerConstants.PASSWORD_TYPE, WSConstants.PW_TEXT); 

     // Callback used to retrieve password for given user. 
     outProps.put(WSHandlerConstants.PW_CALLBACK_CLASS, ServiceTest.class.getName()); 

     WSS4JOutInterceptor wssOut = new WSS4JOutInterceptor(outProps); 
     cxfEndpoint.getOutInterceptors().add(wssOut); 


     try 
     { 
      List list = service.getInpatientCensus(); 
      for(Patient p : list){ 
       System.out.println(p.getFirstName() + " " + p.getLastName()); 
      } 

     } 
     catch (Exception e) 
     { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 
    } 
} 
9

Las especificaciones de WS-Security normalmente no están incluidas en un WSDL (nunca en un WSDL de WSE). Entonces wsdl2java no sabe que WS-Security es incluso necesario para este servicio. El hecho de que las restricciones de seguridad no estén presentes en un WSDL de WSE es una gran decepción para mí (WCF incluirá la información de WS-Trust en un WSDL).

En el extremo del cliente, necesitará usar Rampart para agregar los encabezados de WS-Security necesarios a su mensaje de cliente saliente. Dado que el WSDL no informa qué configuraciones de WS-Security son necesarias, es mejor que se lo pregunte al proveedor de servicios qué se requiere. Los requisitos de WS-Security pueden ser simples palabras clave de texto, o pueden ser certificados X509, o pueden ser mensajes cifrados .....Rampart debería ser capaz de manejar la mayoría de estos escenarios.

Apache Rampart se "enciende" conectando el módulo en su archivo axis2.xml. Deberá descargar el módulo Rampart y colocarlo en un lugar específico en su directorio axis2, luego modificar el archivo xml. También puede participar en Rampart programáticamente (edite su pregunta original si esto es un requisito y editaré esta respuesta).

Dependiendo de cómo configure el arreglo (a través de otros archivos XML o programáticamente), interceptará los mensajes salientes y le agregará la información necesaria de WS-Security. Personalmente he usado axis2 con terraplén para llamar a un servicio WSE3 que está asegurado con UsernameToken en texto plano y funcionó de maravilla. Escenarios similares, pero más avanzados también deberían funcionar. Hay más detalles sobre cómo configurar y comenzar con Rampart en el sitio vinculado anteriormente. Si tiene problemas con los detalles de Rampart o cómo usar Rampart con su configuración de WSE particular, edite su pregunta y haré mi mejor esfuerzo para responder.

Cuestiones relacionadas