扭曲的Web服务器会话匹配/诊断

时间:2019-06-19 12:56:03

标签: python twisted twisted.web

我有一个使用Twisted的现有Web应用程序。客户端是嵌入式设备,而不是人类。因此,我偶尔会遇到这些设备中通常过时且简单的http客户端的怪癖。该应用程序依赖于会话cookie,到目前为止,我还没有遇到任何问题。

最近,我添加了一种新型设备,但是会话匹配无法正常工作。

我正在使用twisted.web.server会话类中的getSession()。

此特定的客户端设备似乎正在以一种getSession无法与会话匹配的格式返回Cookie标头(因此将在收到的每个请求上创建一个新的会话)。

我不确定这是Twisted的问题还是客户端设备格式化Cookie标头的格式问题,特别是它如何重新格式化Path属性。

工作的客户端设备的行为是这样。

Twisted发送的Set-Cookie标头:

Set-Cookie: TWISTED_SESSION=10d4ed8a01ad1459c53018953343f2d357e9ac5015a86ab714fd09eb12b06c4c; Path=/

以及客户端在下一个请求上发送的结果Cookie头:

Cookie: $Version="0"; TWISTED_SESSION=10d4ed8a01ad1459c53018953343f2d357e9ac5015a86ab714fd09eb12b06c4c;$Path=/

现在不工作的客户端,来自Twisted Web服务器的Set-Cookie标头:

Set-Cookie: TWISTED_SESSION=fe5abac62eb577176e94d2a98d46298d6c093d425e51583554a4ad98e3cff8fb; Path=/

以及由此产生的Twisted Session不匹配的Cookie标头:

Cookie: TWISTED_SESSION=fe5abac62eb577176e94d2a98d46298d6c093d425e51583554a4ad98e3cff8fb/

只是将路径“ /”放在TWISTED_SESSION属性的末尾。

对于如何进一步诊断,我有些困惑,我试图重新编写Cookie标头,并从最后删除/,但这无济于事。

我也不确定客户的行为是否正确。这似乎很不正常,但我不知道它在做什么在技术上是否错误。

1 个答案:

答案 0 :(得分:0)

我已经找到解决方法。我想将其发布在这里,以防其他人使用。

简而言之,实际的答案是HTTP客户端已损坏,并错误地发送了Cookie标头。

我很高兴有人提出其他证明,但是从我自己阅读的RFC6265和Mozilla开发人员文档来看,不允许将Path属性附加到另一个cookie(名称=值)对的末尾。鉴于这对名称是任意的,就没有任何意义。

我添加了一个猴子补丁来解决此问题。杂乱无章,但它可以让我进一步测试该设备是否有用:

from twisted.web.http import Request
def parseCookies(self):
    """                                                                                                                                     
    Parse cookie headers.                                                                                                                   

    This method is not intended for users.                                                                                                  
    """
    cookieheaders = self.requestHeaders.getRawHeaders(b"cookie")

    if cookieheaders is None:
    return

    for cookietxt in cookieheaders:
        if cookietxt:
            for cook in cookietxt.split(b';'):
        cook = cook.lstrip()
                try:
                    k, v = cook.split(b'=', 1)
                    self.received_cookies[k] = v.split(b'/')[0]
                except ValueError:
                    pass

Request.parseCookies = parseCookies