背景
项目的业务流程中有一个环节,需要访问供应商提供的web service。不同于公共的服务,由于系统涉及财务,这个服务必须通过认证才能访问。认证的方式是NTLM,是一种windows特有的认证方式,而常规的Http认证会报401错误。
常规的处理思路是用大名鼎鼎的suds库(python3环境下,需要 suds-jurko + suds-py3 这两个库搭配使用)来创建一个Client示例,然后直接打点访问对应的SOAP方法。类似的代码网上随处可见,我就不写了。我这里却遇到了问题(ntml-auth库报错),而不得不另寻出路。
我们都知道SOAP协议,其实也是源自HTTP协议传输的,只是通过XML对方法做了预定义,相比较常见的开放接口而言,WSDL具有很好的方法发现特效。
既然如此,那我们完全可以用http的方式去调用,只要我们自己能够处理好认证、报文和http头即可。
需要用到的库
import requests
from requests_ntlm import HttpNtlmAuth
url = "http://xxxx/aaaaa/bbbb/cccc"
username = "username"
password = "password"
headers = {
"Content-Type": "text/xml",
"SOAPAction": "action" # 你要访问的方法名。必填,否则无法访问到方法,这个地方卡我好久
postcontent='<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body><action xmlns="urn:microsoft-dynamics-schemas/codeunit/cccc"><p1>6541</p1><p2>0</p2></action></soap:Body></soap:Envelope>'
req = requests.post(url, headers=headers, auth=HttpNtlmAuth(username, password), data=postcontent.encode('utf-8'))
print(req, req.text)
报文尽量一行写完,别换行。由于提供的web service是由版本比较低的Nav提供的,xml格式并不是特别规范,如果我们的报文有回车、制表符等字符的话,会报500错误,提示无效的数据。
SOAP的报文,可以通过下一节提到的接口测试工具SoupUI得到。
headers里的Content-Type和SOAPAction都是必填的。Content-Type固定写text/xml,SOAPAction写你要调用的方法名。
requests想通过NTLM认证,需要配合使用requests_ntlm.HttpHtlmAuth。
接口测试工具
我们在开始写代码之前,可以先用接口测试工具检查一下接口的访问性。这里推荐两个工具,(1)SoupUI,(2)Postman
1. SoupUI
操作步骤如图:
(1)创建SOAP项目
理论上SoupUI就能搞定的ws,可以直接用suds来操作。
2. Postman
SoupUI成功了,就可以用Postman来模拟HTTP Request了。这一步再成功了,python下实现就轻而易举了。
操作请看图:
(1)认证这样写,注意TYPE选择NTLM Authentication