chan

朝生暮死不足笑 但悲百年不足道

Django的登录校验机制


他是如何判断我之前用的是哪个id登录的呢。比如说,我之前用的user_id是王强。我使用之前登录的那个浏览器登录,他从服务器session中获取user_id,他是怎么知道获取的是这个浏览器的王强,还是另一个浏览器的张三呢。

ChatGPT 说:

ChatGPT

这个问题的关键在于 Django 的会话机制(Session Mechanism),它是通过 浏览器发送的 Cookie 来区分不同用户和浏览器的。下面分步骤解释 Django 是如何实现这一点的:


1. 浏览器中的 Cookie 关联会话

当用户登录成功后,Django 会在浏览器中设置一个名为 sessionid 的 Cookie,这个 Cookie 是唯一的,用来标识当前会话。具体过程如下:

  1. 用户登录成功:
    • 登录视图会在服务器端创建一个会话记录,并生成一个唯一的 session_key(例如:abc123def456)。
    • Django 将登录用户的 ID(如 user_id = 42)存储到服务器端会话数据中:plaintext复制代码session_key: abc123def456 session_data: {"user_id": 42}
    • 然后 Django 将 session_key 返回给客户端,并存储在浏览器的 Cookie 中:plaintext复制代码Set-Cookie: sessionid=abc123def456; Path=/; HttpOnly
  2. 用户下次请求:
    • 当用户再次发送请求时,浏览器会自动携带之前保存的 sessionid Cookie:plaintext复制代码Cookie: sessionid=abc123def456
    • Django 从 sessionid 中提取 session_key,并根据这个 session_key 找到服务器端的会话数据 {"user_id": 42}

这样,Django 就能够知道这个请求是来自哪个用户,user_id = 42 即代表这个用户。


2. 不同浏览器的区别

每个浏览器的 sessionid 是独立的

  • Django 会为每个新的登录会话生成一个新的 session_key,并存储在对应的浏览器的 Cookie 中。
  • 这意味着:
    • 如果你用浏览器 A 登录王强,浏览器 A 的 sessionid 关联的是王强的会话。
    • 如果你用浏览器 B 登录张三,浏览器 B 的 sessionid 关联的是张三的会话。
  • 浏览器 A 和浏览器 B 的 sessionid 是不同的,因此 Django 可以通过 sessionid 区分开这两个浏览器的请求。

多个用户的情况

  • 如果你在同一个浏览器中登录不同的用户(比如在不同的标签页中登录),后登录的用户会覆盖之前的用户会话。这是因为浏览器的 Cookie 是全局共享的,只有一个 sessionid 被存储。

3. 会话存储在服务器端

Django 会将会话数据存储在服务器端,默认是存储在数据库中(django_session 表)。存储的结构如下:

session_keysession_dataexpire_date
abc123def456{"user_id": 42}2024-01-01 00:00:00
xyz789ghijk{"user_id": 57}2024-01-01 00:00:00
  • Django 使用浏览器发送的 sessionid(如 abc123def456)从数据库中查找到对应的 session_data
  • session_data 中存储的 user_id 是 Django 用于识别用户的关键。

4. 核心流程总结

假设你用浏览器登录用户王强:

  1. 用户登录:
    • Django 为浏览器分配一个唯一的 sessionid
    • 在服务器端会话中,sessioniduser_id 绑定(如 sessionid=abc123def456 -> user_id=42)。
    • 浏览器会保存这个 sessionid
  2. 下次请求:
    • 浏览器会自动带上 sessionid
    • Django 根据 sessionid 找到会话数据,并获取 user_id
    • 然后在代码中 request.session.get('user_id') 返回 42
  3. 多个浏览器:
    • 不同浏览器有不同的 sessionid,所以它们的会话数据互相独立。

5. 示例说明

假设数据库中的会话数据:

session_keysession_datauser_idexpire_date
abc123def456{"user_id": 42}王强2024-01-01 00:00:00
xyz789ghijk{"user_id": 57}张三2024-01-01 00:00:00

浏览器 A 的行为:

  • 登录王强时,浏览器保存:plaintext复制代码Cookie: sessionid=abc123def456
  • 服务器会用 sessionid=abc123def456 找到 {"user_id": 42}

浏览器 B 的行为:

  • 登录张三时,浏览器保存:plaintext复制代码Cookie: sessionid=xyz789ghijk
  • 服务器会用 sessionid=xyz789ghijk 找到 {"user_id": 57}

6. 常见问题

1. 为什么同一浏览器中只能记录一个用户?

这是因为浏览器的 Cookie 是全局共享的,Django 只能为每个浏览器保存一个 sessionid,导致每次新的登录会覆盖旧的会话。

2. 用户会话过期时会发生什么?

如果会话过期(比如 expire_date 到期),Django 会删除对应的会话数据。

  • 浏览器中仍然会携带旧的 sessionid,但 Django 找不到对应的会话,request.session 会返回空。

7. 总结

Django 是通过 Cookie 的 sessionid 来识别不同浏览器和用户的。流程如下:

  1. 用户登录时
    • Django 为浏览器生成唯一的 sessionid,并与用户的 user_id 绑定,存储在服务器端。
    • 浏览器保存这个 sessionid
  2. 用户发送请求时
    • 浏览器携带 sessionid,Django 从会话存储中找到对应的 user_id
  3. 多个浏览器
    • 每个浏览器的 sessionid 是独立的,所以它们的会话互不影响。

通过这种机制,Django 能够区分同一服务器上的不同用户和不同浏览器。

评论
还没有评论
    发表评论 说点什么