Acceder a los header SOAP en programas GeneXus

Un cliente nos pidió que necesitaba un servicio web SOAP, que recibiera un header y realizar con dicha información una validación de seguridad.

Con GeneXus nativo, no tenemos la posibilidad de recuperar los header soap aunque si se pueden setear cuando hago una invocación.

El problema era recibir algo asi (no es con usuario y contraseña, sino con un token, pero lo hago así para el ejemplo).

?xml version = "1.0"?>
<SOAP-ENV:Envelope 
   xmlns:SOAP-ENV = " http://www.w3.org/2001/12/soap-envelope"   
   SOAP-ENV:encodingStyle = " http://www.w3.org/2001/12/soap-encoding">

   <SOAP-ENV:Header>
      <s:Security  xmlns:s = "http://ealmeida.blogspot.com/security/" 
         user="Usuario" password="Peñarol">
      </s:Security>
   </SOAP-ENV:Header>
   ...
   ...
</SOAP-ENV:Envelope>

Teniamos varias opciones:

1) Modificar el programa fuente generado por Genexus, para capturar los header mientras los procesa en un procedure SOAP.
2) Programar el servicio como procedure con call protocol = HTTP, con lo cual nos perdíamos las ventajas de tener el WSDL y hay que procesar a mano todo el request.

Decidimos hacer algo intermedio, que fue hacer un procedure HTTP, que reciba el request SOAP, realice la validación, y luego pase el contenido de dicho request a un servicio interno SOAP.

Una de las contras de este enfoque era que perdíamos la posibilidad de tener el WSDL dinámico como lo tenemos con Genexus.

Para eso, agregamos que si nos llegaba un GET, con parámetro WSDL, recuperamos el WSDL del web service original y lo devolvemos (modificando el location, para que llame al objeto correcto).


Nicolas programó el código del procedure main / call protocol = HTTP de la siguiente forma:
//Recibe &SoapURL es la URL del servicio SOAP (solo interna)          
//       &RestURL es la URL del procedure REST (es este mismo programa)
//Esto para procesar los POST, en un llamado normal al WS
if &HTTPRequest.Method = "POST"
&RequestString = &HTTPRequest.ToString()
&SOAPAction = &HTTPRequest.GetHeader("SOAPAction")
//Valido el header
if ValidateSoapHeader(&RequestString)
//Ejecuto la llamada al web service SOAP
&HTTPClient.AddHeader("SOAPAction", &SOAPAction)
&HTTPClient.AddString(&RequestString)
&HTTPClient.Execute("POST", &SoapURL)
//Armo la respuesta con la respuesta recibida del web service SOAP
&HTTPResponse.AddHeader("Content-Type", "text/xml;charset=utf-8")
&HTTPResponse.AddString(&HTTPClient.ToString())
        else
                //Devuelvo error 403 
endif
endif
//Procesamos los GET, para devolverl el WSDL
if &HTTPRequest.Method = "GET"
&QString = &HTTPRequest.QueryString 
if &QString.ToLower() = "wsdl"
&HTTPClient.AddString(&RequestString)
//Valido el header
if ValidateSoapHeader(&RequestString)
//Ejecuto la llamada al web service SOAP
&HTTPClient.Execute("GET", &SoapURL + "?wsdl")
&ClientResponse = &HTTPClient.ToString()
                        //Esta sustitucion es necesaria para cambiar el  <soap:address location="xxxx" del WSDL 
&ClientResponse = &ClientResponse.Replace(&SoapURL, &RestURL)
&HTTPResponse.AddString(&ClientResponse)
endif
endif
endif
Falta probarlo bien con https (necesita algunos cambios), pero funciona bien para WS desarrollados con GX con varios stubs y diferentes parámetros.

Hay que asegurar con algun mecanismo adicional, para que no se pueda acceder desde afuera al servicio SOAP pues este no tendra la validacion.

 Lo comparto pues posiblemente le pueda servir a alguien mas.

Comentarios

  1. Que bueno, me gusta la solución mas que nada, pues casi ya no uso soap, pero muy buena !

    ResponderEliminar
  2. Excelente, muchas gracias. Llegué a este artículo por un caso relacionado que se me ha presentado: al consumir un web service SOAP como cliente desde Genexus, el web service devuelve un mensaje de error y quien desarrolló el web service nos pide el request que estamos haciendo al invocar el web service. Terminamos utilizando un proxy que tiene muchas funcionalidades: https://www.membrane-soa.org/, permite entre muchas otras cosas "rutear" el consumo hacia el proxy, donde se registran los request y a su vez los redirecciona al web service a consumir, permite utilizar https indicando la ruta del trustore y en caso de ser necesario del keystore.

    ResponderEliminar

Publicar un comentario

1) Lee el post
2) Poné tu opinión sobre el mismo.
Todos los comentarios serán leidos y la mayoría son publicados.

Entradas más populares de este blog

Paleta de colores en GeneXus

Sistema LUCIA: 20 años de una KB en producción.