Respuesta: Cliente SOAP web services compatible con HTTPS y firma digital Cita:
Iniciado por razpeitia 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 |