2

我有一个我正在尝试使用suds访问的 soap 1.1/1.2 Web 服务。

不幸的是,该服务将身份验证令牌放在响应肥皂头中。

是否可以以某种方式访问​​标题?

我知道可以在请求中设置一个自定义的肥皂头,但这不是我想要的。

4

3 回答 3

4

我一直在使用(仍然维护的)suds-jurko 分支,但遇到了麻烦,因为client.last_received()它在分叉后很早就被删除了。所以我不得不想出一种访问标题的替代方法。

幸运的是,您可以使用消息插件来存储已解析的文档,然后通过插件访问标题。为了更加方便,您可以根据服务方法处理标头,而不是使用 xml 文档中的原始值,以获取正确键入/结构化的值。

from suds.plugin import MessagePlugin

class HeaderPlugin(MessagePlugin):
    def __init__(self):
        self.document = None

    def parsed(self, context):
        self.document = context.reply

    def get_headers(self, method):
        method = method.method
        binding = method.binding.output
        rtypes = binding.headpart_types(method, False)

        envns = ('SOAP-ENV', 'http://schemas.xmlsoap.org/soap/envelope/')
        soapenv = self.document.getChild('Envelope', envns)
        soapheaders = soapenv.getChild('Header', envns)
        nodes = soapheaders.children
        if len(nodes):
            resolved = rtypes[0].resolve(nobuiltin=True)
            return binding.unmarshaller().process(nodes[0], resolved)
        return None

用法:

from suds.client import Client

hp = HeaderPlugin()
client = Client(wsdl, plugins=[hp])

response = client.service.LoremIpsum()
headers = hp.get_headers(client.service.LoremIpsum)

示例输出:

>>> headers
(AuthenticationResponseHeader){
   sessionKey = "a631cd00-c6be-416f-9bd3-dbcd322e0848"
   validUntil = 2030-01-01 01:01:01.123456+01:00
 }
>>> headers.validUntil
datetime.datetime(2030, 1, 1, 1, 1, 1, 123456, tzinfo=<suds.sax.date.FixedOffsetTimezone object at 0x7f7347856be0>)
于 2015-04-09T15:09:06.897 回答
2

你可以做类似的事情

print client.last_received().getChild("soap:Envelope").getChild("soap:Header")
.getChild("ResponseHeader").getChild("resultCode").getText()

上面读取了soap头中的一个字段resultCode。您必须为每个字段执行此操作。据我所知,这是阅读标题的后门。

有关详细信息,请查看带有泡沫的肥皂头

于 2012-12-12T17:00:41.530 回答
0

Towr 的类插件运行良好,但是当您在 Soapheader Response 中有多个 obj 时,它会出现问题。他的代码只得到第一个对象。

以下是改进 Towr 类的代码:

class HeaderPlugin(MessagePlugin):
    def __init__(self):
        self.document = None

    def parsed(self, context):
        self.document = context.reply

    def get_headers(self, method):
        Result = {}
        method = method.method
        binding = method.binding.output
        SHeaderElem = binding.headpart_types(method, False)

        envns = ('SOAP-ENV', 'http://schemas.xmlsoap.org/soap/envelope/')
        soapenv = self.document.getChild('Envelope', envns)
        soapheaders = soapenv.getChild('Header', envns)
        SHeaderNodes = soapheaders.children

        for Elem in SHeaderElem:
            for Node in SHeaderNodes:
                if(Node.name == Elem.name):
                    ElemRes = Elem.resolve(nobuiltin=True)
                    NodeRes = binding.unmarshaller().process(Node, ElemRes)
                    Result[Elem.name] = NodeRes
        return Result
    #

为了更好地理解,请参阅示例。如果您收到此 Soap 响应:

<soap-env:Envelope xmlns:eb="http://www.ebxml.org/namespaces/messageHeader" xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/"  xmlns:wsse="http://schemas.xmlsoap.org/ws/2002/12/secext">
    <soap-env:Header>
        <eb:MessageHeader eb:version="1.0" soap-env:mustUnderstand="1">
            <!-- -->
        </eb:MessageHeader>
        <wsse:Security>
            <!-- -->
        </wsse:Security>
    </soap-env:Header>
    <soap-env:Body>
        <!-- -->
    </soap-env:Body>
</soap-env:Envelope>

函数 get_headers 将返回一个像这样的字典:

SoapHeadersResp = {'MessageHeader':MessageHeaderObj, 'Security':SecurityObj}

要使用这个类,只需按照 Towr 所说的相同步骤,用这个替换他的 HeaderPlugin 类。

于 2017-11-18T21:39:24.433 回答