自定义SOAP标头
在服务调用期间,可以使用soapheaders选项传递自定义SOAP标头。自定义soap头被定义为服务所需的头,而不是在wsdl中定义的。不能使用已经描述过的传递soap头的简单方法。是通过构造和传递元素或元素集合来完成的,如下所示:
from suds.sax.element import Element
client = client(url)
ssnns = ('ssn', 'http://namespaces/sessionid')
ssn = Element('SessionID', ns=ssnns).setText('123')
client.set_options(soapheaders=ssn)
result = client.service.addPerson(person)
WS-安全
使用明文密码的UsernameToken提供基本的ws安全性
from suds.wsse import *
security = Security()
token = UsernameToken('username', 'password')
security.tokens.append(token)
client.set_options(wsse=security)
或者,如果需要Nonce和Create元素,可以按如下方式生成和设置:
from suds.wsse import *
security = Security()
token = UsernameToken('username', 'password')
token.setnonce()
token.setcreated()
token.setnonceencoding(True)
token.setpassworddigest('digest')
security.tokens.append(token)
client.set_options(wsse=security)
但是,如果想手动设置Nonce或Created,可以执行以下操作:
from suds.wsse import *
security = Security()
token = UsernameToken('username', 'password')
token.setnonce('NonceString...')
token.setcreated(datetime.now())
security.tokens.append(token)
client.set_options(wsse=security)
http身份验证
HTTP 身份验证基本如下:
client = Client(url, username='***', password='***')
身份验证由Transport.https模块中定义的(默认)HttpAuthenticated Transport类提供,该模块遵循RFC中定义的质询(http 401)/响应模型。
Transport.http模块中添加了一个新的Transport(0.3.7版本及以上),它在所有http请求上设置Authentication:http头。这种方式可按如下方式使用:
from suds.transport.http import HttpAuthenticated
t = HttpAuthenticated(username='***', password='***')
client = Client(url, transport=t)
在suds默认传输中从httplib迁移到urllib2(0.3.3及以上版本),用户能够利用urllib2提供的所有身份验证功能。例如,基本的HTTP身份验证可以实现如下:
myurl = 'http://localhost:7080/webservices/WebServiceTestBean?wsdl'
client = Client(myurl)
import urllib2
baseurl = 'http://localhost:7080/'
username = '***'
password = '***'
passman = urllib2.HTTPPasswordMgrWithDefaultRealm()
passman.add_password(None, baseurl, username, password)
authhandler = urllib2.HTTPBasicAuthHandler(passman)
client.options.transport.urlopener = urllib2.build_opener(authhandler)
suds默认的HTTP传输使用urlib2.urlopen(),如果正确创建传输的urlopener并设置urlopenter,则会自动处理基本的HTTP身份验证。
消息注入 (诊断、测试)
服务API提供消息/回复注入。
要注入要发送的soap消息,或者注入要处理的回复或故障(如同soap服务器返回的一样),只需使用包含以下内容的字典值指定__inject关键字参数:
- msg =
- reply =
- fault =
当调用服务时。如发送原始soap消息:
message = \
"""<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope>
<SOAP-ENV:Body>
...
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>"""
print (client.service.test(__inject={'msg':message}))
注入响应进行测试:
reply = \
"""<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope>
<SOAP-ENV:Body>
...
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>"""
print (client.service.test(__inject={'reply':reply}))
SSL证书验证和自定义证书
在Python 2.7.9,SSL/TLS验证在默认情况下处于启用状态。
当对具有自签名证书的端点使用suds时,这可能是一个问题,这在企业内部网中很常见。
在suds中关闭证书验证的一种方法是使用自定义的传输类。在Python 3如下:
import urllib.request
import ssl
import suds.transport.http
class UnverifiedHttpsTransport(suds.transport.http.HttpTransport):
def __init__(self, *args, **kwargs):
super(UnverifiedHttpsTransport, self).__init__(*args, **kwargs)
def u2handlers(self):
handlers = super(UnverifiedHttpsTransport, self).u2handlers()
context = ssl.create_default_context()
context.check_hostname = False # 关闭验证
context.verify_mode = ssl.CERT_NONE
handlers.append(urllib.request.HTTPSHandler(context=context))
return handlers
client = Client(url, transport=UnverifiedHttpsTransport())
此外,如果需要一组自定义的证书或根CA,也可以通过自定义的传输类来完成。在Python 3如下:
class ClientHttpsTransport(HttpTransport):
def __init__(self, certfile, keyfile, cafile, *args, **kwargs):
super(ClientHttpsTransport, self).__init__(*args, **kwargs)
self.certfile = certfile
self.keyfile = keyfile
self.cafile = cafile
def u2handlers(self):
handlers = super(ClientHttpsTransport, self).u2handlers()
context = ssl.create_default_context(ssl.Purpose.SERVER_AUTH, cafile=self.cafile)
context.load_cert_chain(self.certfile, self.keyfile)
context.check_hostname = False # 关闭验证
context.verify_mode = ssl.CERT_NONE
handlers.append(urllib.request.HTTPSHandler(context=context))
return handlers
custom_https = ClientHttpsTransport('/path/to/certificate_file', '/path/to/key_file', '/path/to/ca_file')
client = Client(url, transport=custom_https),
超时
每个请求的超时可以通过在每个调用中使用__timeout关键字参数来设置。这会取代全局客户端默认设置。例如,以下调用的超时时间为10秒:
client = Client(url, timeout=30)
client.service.test(__timeout=10)
缓存
suds提供了一些URL缓存。默认情况下,缓存获取WSDL和导入XSD。缓存适用于URL,例如用于获取引用的WSDL和XSD模式的URL,但不适用于服务方法调用,因为这没有意义。
在0.3.9中,FileCache被ObjectCache取代。
默认缓存是一个ObjectCache,有效期为(1)天
时间可更改:
import datetime
...
cache = client.options.cache
cache.duration = datetime.timedelta(days=10)
持续时间必须是datetime.timedelta
默认位置(目录)是/tmp/suds,因此Windows用户需要将位置设置在能找到的位置
缓存是一个选项,可以使用任何类型的缓存对象进行设置,也可以通过将选项设置None来禁用缓存。用户可以插入想要的任何类型的缓存
from suds.cache import Cache
class MyCache(Cache)
...
client.set_options(cache=MyCache())
禁用缓存:
client.set_options(cache=None)
修复损坏的模式
有时候在 WSDL 中定义的或导入的模式都被破坏了。最常见的问题是未能按照正确的导入规则导入。也就是说,在一个模式中引用另一个模式中定义的命名对象而不导入它。 doctor
模块定义了一组用于修复损坏的模式的类
如之前的文中提到的错误: suds.TypeNotFound: Type not found: ‘(schema, http://www.w3.org/2001/XMLSchema, ) 就可以使用修复
doctor
该类 Doctor
为提供此服务的类提供接口。option
定义后,可以在创建客户端时指定Doctor
from suds.xsd.doctor import ImportDoctor, Import
imp = Import('http://www.w3.org/2001/XMLSchema') # 导入有错误的schema
imp.filter.add('http://WebXml.com.cn/') # 添加Prefixes 在xml中的Service可以找到
doctor = ImportDoctor(imp)
client = Client(url, doctor=doctor)
对于schemaLocation未绑定到命名空间的情况,可以创建指定位置的Import,如下所示
imp = Import('http://www.w3.org/2001/XMLSchema', location='http://www.w3.org/2001/XMLSchema.xsd')
imp.filter.add('http://WebXml.com.cn/')
doctor = ImportDoctor(imp)
client = Client(url, doctor=doctor)
将schema位置(URL)绑定到命名空间
某些 WSDL 模式导入为:<import namespace=" http://schemas.xmlsoap.org/soap/encoding/%22/ “> without schemaLocation=”" 并期望处理器使用命名空间 URI 作为模式位置名称空间。当未指定 @schemaLocation 时,处理 的规范将导入的命名空间的解析留给处理器(在本例中为 suds)的继承。Suds 总是在 WSDL 中查找模式,但不会在外部查找,除非:
- 指定了 schemaLocation,或者
- 使用以下语法指定静态绑定:
from suds.xsd.sxbasic import Import
ns = 'http://schemas.xmlsoap.org/soap/encoding/'
location = 'http://schemas.xmlsoap.org/soap/encoding/'
Import.bind(ns, location)
# 当 location 和 ns相同时 可以简写成
Import.bind(ns)