每个响应都应该设置cookie头吗?

7 投票
3 回答
5108 浏览
提问于 2025-04-17 19:12

假设你正在实现会话功能。

你会检查浏览器是否有会话的cookie。如果有,你就验证这个cookie,找到和这个会话相关的用户,然后继续处理请求。

如果没有找到会话cookie,你就创建一个新的会话,并发送一个cookie到浏览器,期待在后续的请求中再次收到这个cookie。

我的问题是:如果在请求中找到了会话cookie,你会在响应中重新发送这个cookie吗?在什么情况下这样做是正确的呢?

注意:我问这个问题是因为我是Pyramid(Python)程序员,因为Pyramid的实现会在每次响应中无条件地发送会话cookie。(查看代码)

3 个回答

1

并不是所有的东西都是浏览器。在分布式系统中,比如说你可能在一个节点上登录,然后在其他节点上使用同一个会话来访问服务(如果你有一千个节点,你肯定不想每个都登录一次)。

现在假设其中一个节点发现它的cookie快要过期了,于是它更新了这个cookie。可是其他节点并不知道这个变化,它们可能会再次更新cookie,或者继续使用旧的cookie。无论哪种情况,你的整个系统可能都会出现问题,除非你在节点之间做一些复杂的消息传递。

你可以为这种情况实现类似JWToken的东西,但这也有自己的缺点(比如说不能登出),所以并不总是合适。而且,浏览器也不理解jwtokens。

8

对于一个会话 cookie(也就是浏览器的会话 cookie,客户端在关闭时会立刻删除它),我可能不会这样做。这样做没有特别的意义,而且重复发送这样的信息会浪费一点带宽(虽然量不大)。

> 来,给你一个 cookie。
< 谢谢!
> 不,真的,给你一个 cookie。
< 这不是同一个 cookie 吗?
> 说真的,来,吃这个 cookie。
< 请别这样。

只有在你要改变 cookie 的某些内容时,重新发送 cookie 才有意义。所以如果一个 cookie 有明确的过期时间,你可能会想定期更新这个过期时间。当然,如果你改变了 cookie 中存储的值,你也会重新发送这个信息。

我一般是做 PHP 开发的,PHP 的原生会话也是这样做的(每次都无条件发送)。我想这样做的原因有两个:a) 实现起来更简单,b) 试图考虑到一些用户代理(比如浏览器)可能不按理应的方式工作,可能会忽略过期时间,或者无法将 cookie 写入客户端的持久存储,或者<插入其他奇怪的行为>。

如果每个人都能正确实现 2109/2965 标准,就完全没有必要重复设置语义上相同的 cookie。但是,如果大家真的都去读标准,开发者的生活岂不是太无聊了?

10

一般来说,你不需要在每次响应中都设置cookie。浏览器已经有了这个cookie,只要它还有效,就会继续把它发送给服务器。

具体来说,Pyramid的会话cookie在每次请求时都会被设置,因为它包含一个带签名和时间戳的秘密,这个秘密的过期时间可以和普通cookie的过期机制分开。每次Pyramid设置一个新的cookie时,都会更新里面的时间戳,以显示会话仍然是新鲜的。换句话说,每次设置的cookie都是不同的。

撰写回答