requests.Session() 正在以意想不到的方式处理 cookie(处理 json)

requests.Session() is processing cookie in unexpected way (mangling json)

我在响应客户端请求时填充会话 cookie 服务器端。通过网络,响应如下所示 - 您可以看到 mycookie 具有带转义引号的 json 格式:

21:13:54.006488 IP (tos 0x0, ttl 64, id 45515, offset 0, flags [DF], proto TCP (6), length 303, bad cksum 0 (->89fb)!)
    localhost.http-alt > localhost.57738: Flags [P.], cksum 0xff23 (incorrect -> 0x13f5), seq 1:252, ack 247, win 12751, options [nop,nop,TS val 1223327230 ecr 1223325750], length 251
    0x0000:  4500 012f b1cb 4000 4006 0000 7f00 0001  E../..@.@.......
    0x0010:  7f00 0001 1f90 e18a e6ce bb1d 282c d580  ............(,..
    0x0020:  8018 31cf ff23 0000 0101 080a 48ea 7dfe  ..1..#......H.}.
    0x0030:  48ea 7836 4854 5450 2f31 2e31 2032 3030  H.x6HTTP/1.1.200
    0x0040:  204f 4b0d 0a43 6f6e 7465 6e74 2d54 7970  .OK..Content-Typ
    0x0050:  653a 2061 7070 6c69 6361 7469 6f6e 2f6a  e:.application/j
    0x0060:  736f 6e0d 0a43 6f6e 7465 6e74 2d4c 656e  son..Content-Len
    0x0070:  6774 683a 2032 330d 0a53 6574 2d43 6f6f  gth:.23..Set-Coo
    0x0080:  6b69 653a 2070 6965 6b61 726d 613d 227b  kie:.mycookie="{
    0x0090:  5c22 6372 6561 7465 645c 223a 2031 3438  \"created\":.148
    0x00a0:  3132 3331 3633 325c 3035 3420 5c22 7365  12316324.\"se
    0x00b0:  7373 696f 6e5c 223a 207b 5c22 7573 6572  ssion\":.{\"user
    0x00c0:  5c22 3a20 5c22 686c 6565 6e65 795c 227d  \":.\"my_name\"}
    0x00d0:  7d22 3b20 4874 7470 4f6e 6c79 3b20 5061  }";.HttpOnly;.Pa
    0x00e0:  7468 3d2f 0d0a 4461 7465 3a20 5468 752c  th=/..Date:.Thu,
    0x00f0:  2030 3820 4465 6320 3230 3136 2032 313a  .08.Dec.2016.21:
    0x0100:  3133 3a35 3120 474d 540d 0a53 6572 7665  13:51.GMT..Serve
    0x0110:  723a 2050 7974 686f 6e2f 332e 3420 6169  r:.Python/3.4.ai
    0x0120:  6f68 7474 702f 312e 312e 360d 0a0d 0a    ohttp/1.1.6....

我使用以下请求代码来获取 cookie:

with requests.Session() as s:
    r = s.post(domain+'login')
    c = s.cookies['mycookie']

c看起来像 '"{created: 14812334884 session: {user: hleeney}}"'

c[0] 是“

我在服务器端使用 aiohttp ..

response = web.Response(...)
response.set_cookie(json.dumps({"session":{...}}))

我不确定该怪谁 :D 谁能帮忙?

我怀疑你可能会责怪 Python 的 http.cookies.SimpleCookie

目前的 aiohttp 师傅也许可以帮助您,您的问题看起来与 solved issue.

类似

作为一种选择,您可能会责怪自己——将未签名的 json 存储到 cookie 中是 非常糟糕的 并且 不安全 的想法.通常人们使用 base64 编码和加密签名的字符串。

UPD。 抱歉,aiohttp master 帮不了你——我没注意到数据被 requests 破坏了,而不是 aiohttp

在这里回答 'who to blame' 很难。可能是用户(我)有点无知,如果他更聪明,他就永远不会 运行 陷入这个问题。但是,根据您的观点,它也可以是以下任何一种。这是一个关于软件开发生命周期和标准的有趣案例研究。

1)请求作者: 确实是请求库中的一行有趣的代码正在破坏 JSON。在撰写本文时,它正在覆盖 http/cookies.py 中的代码,以在通过 API 返回它们之前修改 cookie 值。现在,请求人员真的很有帮助而且非常酷。他们承认这个 flaw/sub-optimal 实现,尽管从一个角度来看它并没有真正违背 RFC 6265(据说标准化了 cookie 值)。现在这个缺陷可能支持 'feature' 以与某处的某些服务器端 cookie 代码兼容(我的看法)。存在缺陷的模块被标记为过时,因此在次要版本号上修复和潜在的临时向后兼容性问题被认为是不可取的和浪费。

2) aiohtto_session 的作者: 好吧,该死的,这些人正在将 JSON 放入 cookie 值中!!!他们有错……不是吗?好吧,它又复杂了。他们的目的是为使用 aiohttp 作为服务器的安全会话提供一个简单的 API。他们提供了一些实现。一种用于实时使用的是加密的 cookie,它将会话数据存储在加密的 JSON 字符串中。加密后 encoding/decoding cookie 没有问题。当然,cookie 不是为了在客户端读取,所以它永远不会存在,因为 JSON 和 JSON 永远不会被传输。他们提供的另一个实现是 'Simple' 会话存储。他们在这里放弃加密并将会话作为原始 JSON 字符串传输。这是有问题的,因为 JSON 实际上不应该在 cookie 值中传输(见下面的 3)。然而,简单的会话存储仅用于测试而不是实时..仍然可能更好地提供一个简单的存储,它不会潜在地破坏其他API但实际上有那个实现(JSON没有加密)可能会提供一些有价值的测试覆盖场景。

3)RFC 6265 的作者: 该 RFC 应该在指定 cookie 标准方面具有权威性。它肯定比以前存在的更好。但我不相信它是确定的。 cookie 值的规范有点奇怪和挑剔恕我直言。其一,下面的英语容易产生轻微的误解,其二似乎在省略逗号时出现错别字,而其三......好吧,恕我直言,它又奇怪又挑剔(这里的 H 代表无知,因为我更确保他们知道为什么它有意义)

cookie-value = *cookie-octet / ( DQUOTE *cookie-octet DQUOTE ) cookie-octet = %x21 / %x23-2B / %x2D-3A / %x3C-5B / %x5D-7E ; US-ASCII characters excluding CTLs, ; whitespace DQUOTE, comma, semicolon, ; and backslash 按照现在的方式,将 json 存储在 cookie 中听起来并不疯狂,尽管存在潜在的安全漏洞,人们仍可能希望这样做。在我看来,python HTTP APIs 似乎对不兼容的 cooke 值视而不见 - 它们会转义 DQUOTE 并发送反斜杠。反正不是我的肥皂盒。

4) 用户: 我。好吧,开始这段旅程时,我对以上所有内容一无所知。 cookie 标准及其历史,python http 实施,请求实施,aiohttp_session 实施。我不必要地在客户端测试 cookie 的纯文本值 .. 尽管将来有人可能有真正的理由这样做。我有点随机选择请求来做客户端的事情,所以值得深入研究那里的源代码。

因此,在结束时开个玩笑,我将这一点归咎于微不足道的人类,因为它足够聪明,可以创造复杂性,但又不够聪明,无法避免像这样的 SDLC 问题。