程序员

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

2020-10-26  本文已影响0人  玩物励志老乐

背景

项目的业务流程中有一个环节,需要访问供应商提供的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)

要点讲解

接口测试工具

我们在开始写代码之前,可以先用接口测试工具检查一下接口的访问性。这里推荐两个工具,(1)SoupUI,(2)Postman

1. SoupUI

操作步骤如图:
(1)创建SOAP项目

soupui-1.png
(2)获取方法,替换参数并运行
soupui-2.png
上图第2步所指的XML就是报文了,我们可以复制下来写在python里。

(3)如果需要认证,请看这里


soupui-3.png

理论上SoupUI就能搞定的ws,可以直接用suds来操作。

2. Postman

SoupUI成功了,就可以用Postman来模拟HTTP Request了。这一步再成功了,python下实现就轻而易举了。
操作请看图:
(1)认证这样写,注意TYPE选择NTLM Authentication


postman-1.png

(2)头信息这么写


postman-2.png

(3)报文这么写,要在Body里选择raw,soap:body尽量别换行,整体不换行也没问题


postman-3.png

小结

感觉现在用web service的人很少,所以遇到问题可查阅的资料就更少了。到现在为止,我也不知道自己用suds配合ntlm-auth做的报错原因是什么,不过可以确定的是,错误出在认证这块,不知道是这个wsdl不规范导致ntlm-auth出现了兼容性问题,还是这个库本身就有bug存在。

常规的postman/requests访问web service,网上的资料几乎都有说在headers里加Content-Type的,但是这个SOAPAction几乎没有人提到,要不是我这边瞎几把试,给试出来,我也不知道这个参数这么重要。没有它,只会返回WSDL定义。

这次的头疼之路,通过SoupUI -> Postman -> request 这样的路径解决了。核心就是解决了ntlm验证之后,header里加上SOAPAction这个字段。

这次的事情和爱人讲了,她立刻想到一部讲述图灵的电影(名字忘记了),大概就是图灵在破译敌方电报情报时,通过在电报的头信息里构造了一些数字之后,就成功的破译了,听起来似乎和我这次遇到的情况很像呢。

上一篇下一篇

猜你喜欢

热点阅读