examples - Llamar al servicio web.NET(WSE 2/3, WS-Security) desde Java
netbeans web service from wsdl (6)
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).
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 el control tanto del servicio como del cliente y, por lo tanto, podían realizar ajustes en ambos lados para que funcionara. No estoy en esa posición.
¿Alguien ha hecho esto exitosamente?
@Micro
Hace poco hice una prueba y este es el código que utilicé. No estoy usando políticas, pero utilicé WS-Security con autenticación de texto plano. CXF tiene muy buena documentación sobre cómo lograr esto.
Usé 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();
}
}
}
Creo 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.
CXF - Me gustaría ver 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.
- Apache Axis puede generar un código de proxy desde WSDL http://ws.apache.org/axis/java/user-guide.html#UsingWSDLWithAxis
- NetBeans con el complemento RESTful Web Services puede generar código para usted. Las instrucciones para un cliente de ejemplo para el servicio web de compras de eBay se encuentran en http://ebay.custhelp.com/cgi-bin/ebay.cfg/php/enduser/std_adp.php?p_faqid=1230 .
Las especificaciones de WS-Security normalmente no están contenidas 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 lado del cliente, deberá 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 contraseñas de texto simple, 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" al activar 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 rampart (a través de otros archivos XML o programáticamente), interceptará los mensajes salientes y 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.
Esta parece ser una pregunta popular, así que proporcionaré una descripción general de lo que hicimos en nuestra situación.
Parece que los servicios integrados 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 nuevo ( 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.
Entonces, los pasos que teníamos que hacer, en pocas palabras:
- Lea policyCache.config e intente comprenderlo. Luego reescríbalo en una política que terraplén podría entender. (Algunos documentos actualizados 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.
- Configura 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 una gran cantidad de 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, al único proveedor) para asegurarse de que todo sea interoperativo?
Como postdata agregaré que no terminé haciendo el trabajo, era alguien más en mi equipo, pero creo que obtuve los detalles más sobresalientes. La otra opción que estaba considerando (antes de que mi compañero de equipo asumiera el control) era llamar directamente a la API de WSS4J para construir el sobre SOAP, ya que el servicio .NET lo esperaba. Creo que eso también hubiera funcionado.