Python3如何访问需要NTLM认证的Web Service

背景

项目的业务流程中有一个环节,需要访问供应商提供的web service。不同于公共的服务,由于系统涉及财务,这个服务必须通过认证才能访问。认证的方式是NTLM,是一种windows特有的认证方式,而常规的Http认证会报401错误。

常规的处理思路是用大名鼎鼎的suds库(python3环境下,需要 suds-jurko + suds-py3 这两个库搭配使用)来创建一个Client示例,然后直接打点访问对应的SOAP方法。类似的代码网上随处可见,我就不写了。我这里却遇到了问题(ntml-auth库报错),而不得不另寻出路。

我们都知道SOAP协议,其实也是源自HTTP协议传输的,只是通过XML对方法做了预定义,相比较常见的开放接口而言,WSDL具有很好的方法发现特效。

既然如此,那我们完全可以用http的方式去调用,只要我们自己能够处理好认证、报文和http头即可。

需要用到的库

  • requests
  • requests-ntlm
  • 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