【问题标题】:SOAPpy WSDL client authenticationSOAPpy WSDL 客户端身份验证
【发布时间】:2025-09-05 11:15:02
【问题描述】:

我正在尝试使用 WSDL 和身份验证进行简单的 SOAP 调用,但不知道如何将凭据传递给调用。 WSDL 可以做到这一点,还是我应该以其他方式做到这一点?

from SOAPpy import WSDL

WSDLFILE = 'link/to/wsdl/file'
server = WSDL.Proxy(WSDLFILE)

result = server.methodCall()

现在,我收到此错误:

File "/usr/lib/pymodules/python2.7/SOAPpy/Client.py", line 263, in call
raise HTTPError(code, msg)
SOAPpy.Errors.HTTPError: <HTTPError 401 Unauthorized>

【问题讨论】:

  • SOAPpy 已弃用,取而代之的是 suds - 我已经成功使用了 suds,请查看他们的示例。
  • @Monkey 谢谢,这两者之间有令人难以置信的区别 - 肥皂水要容易得多。
  • @Monkpit 和 @orhesto - suds 似乎已被放弃,SOAPpy 也是如此,尽管fresh 比 suds...
  • @Greg0ry 我发现 suds 在实际工作方面做得更好:) 无论年龄大小。
  • 同意,不过看起来您也可以让 SOAPpy 在这种情况下工作。出于兴趣 - 我找不到比 suds 或 SOAPpy 更好的东西了,有没有这样的项目仍然存在?还是网络服务正在消亡?

标签: python web-services soap wsdl soappy


【解决方案1】:

这是一个很老的问题,但是因为它在谷歌搜索“SOAPpy 身份验证”时首先出现 - 我会留下我的发现,所以也许你不必在 10 小时内敲你的脑袋。回馈社区。​​p>

谷歌搜索没有提供太多帮助,但这里的示例 (http://code.activestate.com/recipes/444758-how-to-add-cookiesheaders-to-soappy-calls/) 让我编写了自己的帮助程序(0.0 版测试版)

from SOAPpy import (
    WSDL,
    HTTPTransport,
    Config,
    SOAPAddress,
)
import urllib2
import base64

class AuthenticatedTransport(HTTPTransport):
    _username = None
    _password = None

    def call(self, addr, data, namespace, soapaction = None, encoding = None, http_proxy = None, config = Config, timeout = 10):
        if not isinstance(addr, SOAPAddress):
            addr = SOAPAddress(addr, config)

        content_type = 'text/xml'
        if encoding != None:
            content_type += '; charset="%s"' % encoding

        encoded_auth = None
        if ( isinstance(AuthenticatedTransport._username, str) != False ):
            if ( isinstance(AuthenticatedTransport._password, str) == False ):
                AuthenticatedTransport._password = ""
            encoded_auth = base64.b64encode('%s:%s' % (self._username, self._password))

        this_request = None
        if ( encoded_auth is not None ):
            this_request = urllib2.Request(
                url=addr.proto + "://" + addr.host + addr.path,
                data=data,
                headers={
                    "Content-Type":content_type,
                    "SOAPAction":"%s" % soapaction,
                    "Authorization":"Basic %s" % encoded_auth
                }
            )
        else:
            this_request = urllib2.Request(
                url=addr.proto + "://" + addr.host + addr.path,
                data=data,
                headers={
                    "Content-Type":content_type,
                    "SOAPAction":"%s" % soapaction,
                }
            )

        response = urllib2.urlopen(this_request)
        data = response.read()

        # get the new namespace
        if namespace is None:
            new_ns = None
        else:
            new_ns = self.getNS(namespace, data)

        # return response payload
        return data, new_ns

WSDL.Config.strictNamespaces = 0

username = "your_username"
password = "your_password"

WSDLFile = "https://%s:%s@some_host/your_wsdl.php?wsdl" % (username, password)
namespace = "http://futureware.biz/mantisconnect"
proxy = WSDL.Proxy(WSDLFile, namespace=namespace, transport = AuthenticatedTransport(username,password))

print(proxy.mc_get_version()) # This is my WSDL call, your will be different

无论出于何种原因,使用 AuthenticatedTransport 类是不够的,WSDL url 本身也必须包含用户名和密码。可能是因为这里被 WSDL 调用的 SOAP 包装器正在创建单独的 HTTP 会话(记得在 SOAPpy 邮件列表中阅读它)。

希望这对某人有所帮助。

【讨论】: