Ver Mensaje Individual
  #3 (permalink)  
Antiguo 30/06/2015, 02:42
davidadanu
 
Fecha de Ingreso: junio-2012
Ubicación: Barcelona
Mensajes: 12
Antigüedad: 12 años, 3 meses
Puntos: 1
Respuesta: Cliente SOAP web services compatible con HTTPS y firma digital

Cita:
Iniciado por razpeitia Ver Mensaje
Yo he usado suds y me ha funcionado bien.

[url]http://stackoverflow.com/questions/6277027/suds-over-https-with-cert[/url]
Hola razpeitia,
suds es con el que más lo he intentado pero sin suerte.

A continuación realizaré una prueba con el mismo código que se muestra en el link que me pasas para ver si podemos solucionarlo a nivel de suds.

Especificaciones:
- SO: Debian 8.1
- Python: 2.7.9
- Suds 0.4
- Uso de entorno virtual de Python para el proyecto
- Firma digital (no auth con certificado sino token WS-SECURITY en las cabeceras del XML), creo que se puede realizar con "SudsSigner" si consigo hacer funcionar suds primero.

Resultados:

El primer error:
Código:
Traceback (most recent call last):
  File "webservices.py", line 76, in <module>
    client = Client(WSDL, location=URL)  #, transport=transport)
  File "/home/www/virtualenv/ws_test/local/lib/python2.7/site-packages/suds/client.py", line 112, in __init__
    self.wsdl = reader.open(url)
  File "/home/www/virtualenv/ws_test/local/lib/python2.7/site-packages/suds/reader.py", line 152, in open
    d = self.fn(url, self.options)
  File "/home/www/virtualenv/ws_test/local/lib/python2.7/site-packages/suds/wsdl.py", line 136, in __init__
    d = reader.open(url)
  File "/home/www/virtualenv/ws_test/local/lib/python2.7/site-packages/suds/reader.py", line 79, in open
    d = self.download(url)
  File "/home/www/virtualenv/ws_test/local/lib/python2.7/site-packages/suds/reader.py", line 95, in download
    fp = self.options.transport.open(Request(url))
  File "/home/www/virtualenv/ws_test/local/lib/python2.7/site-packages/suds/transport/https.py", line 60, in open
    return  HttpTransport.open(self, request)
  File "/home/www/virtualenv/ws_test/local/lib/python2.7/site-packages/suds/transport/http.py", line 62, in open
    return self.u2open(u2request)
  File "/home/www/virtualenv/ws_test/local/lib/python2.7/site-packages/suds/transport/http.py", line 118, in u2open
    return url.open(u2request, timeout=tm)
  File "/usr/lib/python2.7/urllib2.py", line 431, in open
    response = self._open(req, data)
  File "/usr/lib/python2.7/urllib2.py", line 449, in _open
    '_open', req)
  File "/usr/lib/python2.7/urllib2.py", line 409, in _call_chain
    result = func(*args)
  File "/usr/lib/python2.7/urllib2.py", line 1240, in https_open
    context=self._context)
  File "/usr/lib/python2.7/urllib2.py", line 1197, in do_open
    raise URLError(err)
urllib2.URLError: <urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:581)>
Este error parece estar en las versiones de Python 2.7.9 en adelante, al parecer no es capaz de encontrar los certificados CA del pc, lo he intentado incluso especificando la ruta completa al CA pero no lo detecta. Así que para solucionarlo ignoramos la verificación del CERT CA, cosa que me gustaría poder corregir en un futuro, si alguna sabe como configurar correctamente Python para que detecte bien los CA se lo agradecería.


Para arreglar el problema expuesto arriba, aplico el siguiente código de prueba del que he eliminado las URLS por motivos de privacidad, reemplazenlas con cualquier URL de Web services en https:

Código:
# -*- coding: utf-8 -*-
from suds.client import Client
from suds.transport.http import HttpTransport, Reply, TransportError
import urllib2, httplib, socket
import ssl
from httplib import HTTPConnection, HTTPS_PORT


HOST = "webservices.es"
URL = "https://%s/ws/i01/gapt/00001" % HOST
WSDL = "%s?wsdl" % URL


class HTTPSConnection(httplib.HTTPConnection):
    default_port = HTTPS_PORT

    def __init__(self, host, port=None, key_file=None, cert_file=None,
            strict=None, timeout=socket._GLOBAL_DEFAULT_TIMEOUT,
            source_address=None):
        HTTPConnection.__init__(self, host, port, strict, timeout,
                source_address)
        self.key_file = key_file
        self.cert_file = cert_file

    def connect(self):
        sock = socket.create_connection((self.host, self.port),
                self.timeout, self.source_address)
        if (self._tunnel_host):
            self.sock = sock
            self._tunnel()
        self.sock = ssl.wrap_socket(sock, self.key_file, self.cert_file, ssl_version=ssl.PROTOCOL_TLSv1)


class HTTPSHandler(urllib2.HTTPSHandler):
    def __init__(self):
        urllib2.HTTPSHandler.__init__(self)

    def https_open(self, req):
        return self.do_open(self.getConnection, req)

    def getConnection(self, host, timeout=300):
        context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
        context.verify_mode = ssl.CERT_NONE
        context.check_hostname = False
        return httplib.HTTPSConnection(host, context=context)


class HttpsTransport(HttpTransport):
    def __init__(self, **kwargs):
        HttpTransport.__init__(self, **kwargs)
        self.handler = HTTPSHandler()
        self.urlopener = urllib2.build_opener(self.handler)

    def open(self, request):
        return HttpTransport.open(self, request)

    def send(self, request):
        return HttpTransport.send(self, request)


import logging
logging.basicConfig(level=logging.INFO)
logging.getLogger('suds.client').setLevel(logging.DEBUG)
logging.getLogger('suds.transport').setLevel(logging.DEBUG)
logging.getLogger('suds.xsd.schema').setLevel(logging.DEBUG)
logging.getLogger('suds.wsdl').setLevel(logging.DEBUG)


if (__name__ == '__main__'):
    transport = HttpsTransport()
    client = Client(WSDL, location=URL, transport=transport)  # Aquí falla
    print(client)

Este código da como resultado lo siguiente:
Código:
DEBUG:suds.wsdl:reading wsdl at: https://webservices.es/ws/i01/gapt/00001?wsdl ...
DEBUG:suds.transport.http:opening (https://webservices.es/ws/i01/gapt/00001?wsdl)
Traceback (most recent call last):
  File "webservices.py", line 76, in <module>
    client = Client(WSDL, location=URL, transport=transport)
  File "/home/www/virtualenv/ws_test/local/lib/python2.7/site-packages/suds/client.py", line 112, in __init__
    self.wsdl = reader.open(url)
  File "/home/www/virtualenv/ws_test/local/lib/python2.7/site-packages/suds/reader.py", line 152, in open
    d = self.fn(url, self.options)
  File "/home/www/virtualenv/ws_test/local/lib/python2.7/site-packages/suds/wsdl.py", line 136, in __init__
    d = reader.open(url)
  File "/home/www/virtualenv/ws_test/local/lib/python2.7/site-packages/suds/reader.py", line 79, in open
    d = self.download(url)
  File "/home/www/virtualenv/ws_test/local/lib/python2.7/site-packages/suds/reader.py", line 95, in download
    fp = self.options.transport.open(Request(url))
  File "Adam.py", line 58, in open
    return HttpTransport.open(self, request)
  File "/home/www/virtualenv/ws_test/local/lib/python2.7/site-packages/suds/transport/http.py", line 64, in open
    raise TransportError(str(e), e.code, e.fp)
Esto es lo más lejos que he podido llegar, si alguien me puede guiar para solucionarlo estaría muy agradecido.

Saludos y gracias