什么是会话?它们如何工作?

430

我刚开始学习使用Python进行Web应用程序开发。在学习过程中遇到了“cookies”和“sessions”这两个术语。我知道cookie可以将一些信息以键值对的形式存储在浏览器上。但是在session方面,我有一点困惑,在session中我们也是将数据存储在用户浏览器上的cookie中。

例如,当我使用 username='rasmus'password='default' 登录时,数据将被发送到服务器进行身份验证并登录。然而,在整个过程中,服务器还会生成一个会话ID,该ID将存储在我的浏览器上的cookie中。现在,服务器还将此会话ID存储在其文件系统或数据存储中。

但基于仅会话ID,它如何能够在我随后遍历网站时知道我的用户名?它是否将数据作为字典存储在服务器上,其中键将是会话ID,而像 usernameemail 等详细信息将是值?

我有点困惑。需要帮助。


11
它会将数据存储在服务器上,以字典的形式存储,其中键是会话ID,值包括用户名、电子邮件等细节信息。是的,“dict”可能是关系型数据库,但基本原理是这样的。 - bobince
如果你不知道的话:在客户端存储密码是不安全的,即使密码已经被哈希(实际上并没有什么区别。黑客可以通过创建一个虚假的cookie直接输入哈希后的密码)。有更好的方法来存储登录状态。 - cytsunny
1
我使用协议级别的细节编写了自己的代码 - http://www.bitspedia.com/2012/05/how-session-works-in-web-applications.html - Asif Shahzad
6个回答

522
由于HTTP是无状态的,为了将一个请求与其他请求关联起来,您需要一种在HTTP请求之间存储用户数据的方法。
Cookie或URL参数(例如http://example.com/myPage?asd=lol&boo=no)都是在两个或多个请求之间传输数据的合适方式。然而,如果您不希望这些数据在客户端上可读/可编辑,则它们不是很好的选择。
解决方案是将这些数据存储在服务器端,并赋予其一个“id”,然后让客户端仅知道(并在每个HTTP请求中传回)该“id”。这样就实现了会话。或者,您可以使用客户端作为便利的远程存储,但您需要加密数据并将其保留在服务器端。
当然,还有其他方面需要考虑,比如您不希望其他人劫持其他人的会话,您希望会话不会永久存在而是会过期等等。
在您的特定示例中,在成功识别后,用户ID(可以是用户名或用户数据库中的另一个唯一ID)将存储在会话数据中,服务器端。然后,对于从客户端收到的每个HTTP请求,会话ID(由客户端提供)将指向正确的会话数据(由服务器存储),其中包含已经认证的用户ID - 这样您的代码就知道它正在与哪个用户交互。

3
“你不希望客户端保留那些数据。” 为什么?如果你使用强加密,你可以让客户端将会话数据加密并存储在cookie中。这样做可以大大简化扩展到多个节点的过程,因为服务器不需要“记住”任何信息。 - Matt Harrison
6
@MattHarrison,如果不在服务器端“记住任何东西”,你将如何解密数据?无论如何,我已经尝试在我的答案中扩展了这个话题。 - Luke404
6
请注意,将大量数据存储在用户端会增加您的流量。 - nitsas
7
如果第三方能够拦截用户的会话密钥,那么他们不就可以冒充用户吗?假设该网站没有使用HTTPS,即使密钥已加密,第三方也可以使用会话密钥伪装成用户。服务器只需对其进行解密即可。 - user137717
5
是的,如果您允许每个人都使用正确的"会话ID"访问会话,那是有可能的。您可以设置多个限制措施,其中一个最简单和常见的方法是将客户端IP地址存储在会话中:如果来自其他IP地址的客户端呈现相同的会话ID,则将其标记为伪造并删除该会话。 - Luke404
显示剩余6条评论

207

通过图片解释:

Sessions explained via Picture

**脚注 - 暂时忽略。**
你可以把一个会话想象成一张图书馆借书卡。每次你去图书馆,你都要出示你的借书卡,这张卡是由那个特定的图书馆发给你的。这样他们就能将你与存档中的记录匹配起来。
让我们一步一步详细解释:

通过类比的简单解释

想象一下,你在银行里,想要从你的账户里取钱。但是很黑,银行一片漆黑,没有光。你被其他20个人包围着。他们看起来都一样。每个人都有相同的声音。每个人都有可能是坏人。换句话说,HTTP是无状态的。
这家银行是一家有趣的银行 - 为了论证,我们来看看事情是如何运作的:
  1. 你和出纳员交谈,提出取钱的请求,然后
  2. 你必须在沙发上稍等片刻,20分钟后
  3. 你从出纳员那里领取你的钱。

但是出纳员怎么能把你和其他人区分开呢?

出纳员无法看到或者很容易辨认出你,记住,因为灯都灭了。
如果你的出纳把你的1万美元取款交给了别人 - 错误的人?!出纳能够认出你是提款人是非常重要的,这样你才能拿到你要求的钱(或资源)。
解决方案:
当你第一次出现在出纳面前时,他或她会告诉你一个秘密:
“每当你和我交谈时,”出纳说,“你应该首先以GNASHEU329的身份自我介绍 - 这样我就知道是你。”
没有其他人知道这个秘密密码。
我取款的示例:
所以我决定去休息20分钟,然后再去找出纳说:“我想取款。”
出纳问我:“你是谁?!”
“是我,乔治·班克斯先生!”
“证明一下!”
然后我告诉他们我的密码:GNASHEU329
“当然,班克斯先生!”
那基本上就是一个会话的工作原理。它可以在成千上万的人中唯一地识别一个人。每次与出纳员打交道时,你都需要进行身份验证。
会话和Cookie的区别:
Cookie:你可以将Cookie看作是一张塑料卡,上面印有信息。你可以在这张卡上存储任何东西,比如姓名、年龄、性别、婚姻状况、密码等。
会话:将其视为临时通行证。通行证存储在Cookie中,但这并不意味着它本身就是一个Cookie。
还记得上面的通行证吗?GNASHEU329。如果银行先生心机重重,决定修改数字,将最后一位改为GNASHEU320。这样做存在安全隐患:
你不希望任何人都能轻易篡改他人的通行证,或者轻易复制它,下面是一些例子:
与Cookie相关的安全问题:
银行可以在你的卡上写入信息,你也可以。但这可能是危险的。
name: Ben Koshy
sex: male
bank balance: $1.99 :'(

如果我想要偷偷摸摸的话,我可以修改我的身份证。
name: Ben Koshy
sex: male
bank balance: $1 billion bucks.  <------ new line

万岁!我可以印更多的钱,比耶伦鲍威尔加在一起还多。这会带来安全风险:因此银行会在cookie上“加密”信息,这样如果你篡改了它,银行就会知道。一般规则是,你永远不应该把任何可能被篡改的东西,比如银行余额或其他信息,放在cookie里。银行余额应该存储在服务器上,这样没有人可以直接篡改它。
在这种情况下,鲍威尔决定篡改他的cookie中的银行余额。银行现在可以使他的会话无效,并永久注销他。
name: Jerome Powell
title: "independent" bureaucrat - "Chairman of the Fed"
skill: lying to congress;.
session: tampering with the Fed's balance sheet,              
         criminal inflation, quantitative easing, 
         insolvent fed, destroying the dollar,
         endless bailouts, telling everyone at the NY economic
         club that bond yields are rising def. NOT because of
         inflation.....riiiiiiight
         -> session invalid. log him out the fed, permanently. 

再见先生!
复制会话
想想任何基于网络的服务:Facebook、Gmail:如果我有你的密码,那么我就能访问你的账户。会话也是如此:如果我能够复制或重新创建你的会话,那么我就实际上拥有了你的密码,我可以冒充你。
如果你非常粗心大意,不小心在互联网上泄露了你的私钥,这种情况可能会发生。最近(2023年2月)有人在Github上发布了一些私钥。如果他们发布了Github的secret_base_key,这是他们Rails应用程序中的一个随机数,那么我就可以使用那个私钥来创建会话。一旦我创建了一个会话,我就可以有效地冒充别人。
**脚注:上面的图片并不完全准确,因为会话将由“服务器”分配 - 这通常是一个随机数。我想简化解释,所以我有点作弊,使用了一个略微不准确的类比,以便你能大致理解这个概念。我们可以稍后专注于具体细节。图书馆卡的类比更准确。如果你想要超级技术性的解释,可以查看cookie规范:https://httpwg.org/http-extensions/draft-ietf-httpbis-rfc6265bis.html

17
喜欢这个解释 - 在您的比喻中,您将如何防止其他人窃听并听到传达给您的秘密口令?换句话说,如果session_id被盗,有没有可能有人模仿您的凭据? - wmock
3
美好的例子!它应该与渴望学习的人分享! - Victor
在您的类比中,GNASHEU329 是用户密码,它生成一个授权令牌,该令牌在特定时间之前过期;然后 Banks 先生可以使用授权令牌进行多次连续取款,而无需反复向出纳员提供密码。 - Daniel Lizik
在这个比喻中,饼干和会话分别代表什么?它们有何不同之处?另外,如果一个会话关闭了,重新打开时如何获取新信息?谢谢:D - BeastCoder
@BeastCoder 很好的问题,我需要回来给予它应有的关注。请耐心等待。 - BenKoshy
显示剩余3条评论

55
"Session" 是指用户在浏览网站时的时间。它表示从用户第一次进入网站页面到停止使用网站的时间。实际上,我们无法知道用户何时完成了对该网站的使用。在大多数服务器中,会有一个超时时间,除非同一用户请求了另一个页面,否则会自动结束会话。
当用户第一次连接时,会创建某种类型的会话 ID(如何创建取决于 Web 服务器软件和站点上使用的身份验证/登录类型)。与 cookie 类似,这通常不再通过 URL 发送,因为这是一个安全问题。相反,它与其他一些内容一起存储,这些内容也被称为会话。会话变量就像 cookie - 它们是随着页面请求发送的名称-值对,并且随着从服务器返回的页面返回 - 但其名称是在 Web 标准中定义的。
一些会话变量作为 HTTP headers 传递。它们在每个页面浏览的幕后背景中来回传递,因此它们不会出现在浏览器中并向所有人显示可能是私人的信息。其中包括 USER_AGENT(请求页面的浏览器类型)、REFERRER(链接到正在请求的页面的页面)等。一些 Web 服务器软件添加了它们自己的标头或传输特定于服务器软件的其他会话数据。但是标准的已经被很好地记录下来了。
希望这能帮到你。

我知道在我使用的IIS服务器上,可以从USER_NAME头获取用户名,但这可能是特定于IIS的。 - Tim Rourke
这里的 REFERRER 是什么意思? - Gab是好人
@Gab是好人 REFERRER通常指客户端在“Referer”HTTP请求标头中发送的任意字符串,它应该包含引用客户端到当前资源的资源的URL。 - Luke404
谢谢,这应该是如此,但不一定。所以我认为人们经常使用这个标头与RFC中建议的语义不同,对吧? - Gab是好人
你先写了像cookies一样,这通常不再通过URL发送,然后又写了会话变量就像cookies - 它们是随着页面请求发送的名称-值对。具体发生了什么?它会在下次发出任何请求时发送吗? - ajaysinghnegi
顺便提一下,服务器和浏览器之间发送的信息也取决于WebService(例如Apachie)和服务器端脚本语言(例如PHP),以及可能使用的任何框架(例如Symfony)。在我的情况下,至少一些会话的全局变量被发送到浏览器,但不会在页面中公开。据我所知,这些变量非常安全,无法通过JavaScript或浏览器的Inspect/Debugger查看。当页面向服务器发出请求时,这些非常隐藏的值也会发送到服务器以恢复其会话变量。 - user2505564

21

HTTP 是一种无状态的连接协议,即服务器不能区分不同用户的不同连接。

因此,Cookie 应运而生。当客户端第一次连接到服务器时,服务器会生成一个新的会话 ID,并将其作为 Cookie 值发送给客户端。从此以后,这个会话 ID 将标识该客户端连接,因为在每个 HTTP 请求中,它都会在 Cookie 中看到相应的会话 ID。

现在对于每个会话 ID,服务器保留一些数据结构,使他能够存储特定于用户的数据。您可以抽象地称这个数据结构为“会话”。


2
你能详细解释一下这句话吗 - “现在对于每个会话ID,服务器都保留了一些数据结构,使其能够存储特定于用户的数据,这个数据结构可以抽象地称为会话。”?服务器存储了哪些具体的客户端信息? - realPK
你能详细解释一下这句话吗 - “现在对于每个会话ID,服务器都保留了一些数据结构,使其能够存储特定于用户的数据,这个数据结构可以抽象地称为会话。”?服务器存储了哪些具体的客户端信息? - Gab是好人
同样的问题,如果您回复一下会很有帮助。 - Suraj Jain

13

把HTTP想象成一个有短时记忆丧失的人(A),当一个人离开视线后,他会马上忘记那个人。

现在,为了记住不同的人,A拍下那个人的照片并保存下来。每个人的照片都有一个ID编号。当那个人再次出现在视线中时,它告诉A它的ID号码,A就能通过ID号码找到他们的照片。 然后,哇!!,A知道是谁了。

HTTP也是一样,它患有短时记忆丧失。它使用会话(Session)记录您在使用网站时所做的一切,然后当您再次访问时,它借助Cookies(Cookie就像令牌)来识别您。 这里的“照片”就是Session,“ID”就是Cookie。


10

Session 是一个广义的技术术语,可以用来指代使用内存缓存在服务器端存储的状态,也可以用来指代在客户端使用 cookielocal storage 或者 session storage 存储的状态。

浏览器或服务器上没有专门称为“session”的东西。Session 是表示 Web 上用户会话的一种数据类型,这些数据可以存储在服务器或客户端上。

它是如何存储和共享的是另一个话题。简要来说,当用户登录时,服务器会创建 session 数据并生成一个 session ID。该 session ID 以自定义头部或 set-cookie 头部的形式返回给用户,并负责自动将其存储在用户的浏览器中。然后,下一次用户访问网站时,session ID 将随请求一起发送,并由服务器检查该 ID 是否存在现有会话,并相应地处理。

您可以在 session 中存储任何您想要的内容,但主要目的是记住之前访问过您站点的用户(浏览器),无论是有关登录、购物车还是其他活动。

这也是保护 session ID 不被黑客拦截并用于标识自己为另一个用户的重要性所在。

通过阅读 Cookie 的相关内容,您将了解 session 的概念:(https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Cookies)

来自 MDN 的摘录:

Cookies are mainly used for three purposes:

Session management

    Logins, shopping carts, game scores, or anything else the server should remember
Personalization

    User preferences, themes, and other settings
Tracking

    Recording and analyzing user behavior

这是我困惑的地方:会话(session)总是与Cookie相关联,但令牌(token)认证呢?难道令牌认证也不能进行会话控制吗? - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接