4

默认的 Python xmlrpc.client.Transport(可以与 一起使用xmlrpc.client.ServerProxy)不保留 cookie,基于 cookie 的登录有时需要这些 cookie。

例如,以下代理与 TapaTalk API(该login方法使用 cookie 进行身份验证)一起使用时,在尝试修改帖子时将给出权限错误。

proxy = xmlrpc.client.ServerProxy(URL, xmlrpc.client.Transport())

网上有一些Python 2 的解决方案,但它们与 Python 3 不兼容。

如何使用Transport保留 cookie 的?

4

2 回答 2

5

GermainZ 的现有答案仅适用于 HTTP。在与它斗争了很多时间之后,有 HTTPS 适应。请注意context至关重要的选项。

class CookiesTransport(xmlrpc.client.SafeTransport):
    """A SafeTransport (HTTPS) subclass that retains cookies over its lifetime."""

    # Note context option - it's required for success
    def __init__(self, context=None):
        super().__init__(context=context)
        self._cookies = []

    def send_headers(self, connection, headers):
        if self._cookies:
            connection.putheader("Cookie", "; ".join(self._cookies))
        super().send_headers(connection, headers)

    def parse_response(self, response):
        # This check is required if in some responses we receive no cookies at all
        if response.msg.get_all("Set-Cookie"):
            for header in response.msg.get_all("Set-Cookie"):
                cookie = header.split(";", 1)[0]
                self._cookies.append(cookie)
        return super().parse_response(response)

原因是ServerProxy不尊重contexttransport相关的选项,如果指定了transport,我们需要直接在Transport构造函数中使用。

用法:

import xmlrpc.client
import ssl


transport = CookiesTransport(context=ssl._create_unverified_context())
# Note the closing slash in address as well, very important
server = xmlrpc.client.ServerProxy("https://<api_link>/", transport=transport)

# do stuff with server
server.myApiFunc({'param1': 'x', 'param2': 'y'})
于 2017-11-14T17:22:45.940 回答
1

这是一个简单的Transport子类,它将保留所有 cookie:

class CookiesTransport(xmlrpc.client.Transport):
"""A Transport subclass that retains cookies over its lifetime."""

    def __init__(self):
        super().__init__()
        self._cookies = []

    def send_headers(self, connection, headers):
        if self._cookies:
            connection.putheader("Cookie", "; ".join(self._cookies))
        super().send_headers(connection, headers)

    def parse_response(self, response):
        for header in response.msg.get_all("Set-Cookie"):
            cookie = header.split(";", 1)[0]
            self._cookies.append(cookie)
        return super().parse_response(response)

用法:

proxy = xmlrpc.client.ServerProxy(URL, CookiesTransport())

由于xmlrpc.client在 Python 3 中为此提供了更合适的钩子,因此它比等效的 Python 2 版本简单得多。

于 2014-09-16T19:02:17.393 回答