一、为什么需要 Cookie 与 Session?
HTTP 是一种无状态协议。这意味着每次客户端检索网页时,客户端打开一个单独的连接到 Web 服务器,服务器会自动不保留之前客户端请求的任何记录。
问题: 用户登录后,下一次请求时服务器如何知道"来的人是谁"?
解决: 使用 Cookie 与 Session 来维持客户端与服务器之间的会话状态。
| 技术 | 存储位置 | 安全性 | 容量限制 |
|---|---|---|---|
| Cookie | 客户端浏览器 | 较低(明文文本) | 约 4096 字节 |
| Session | 服务器端 | 较高 | 无明确限制 |
核心思路: Cookie 负责识别用户(存一个随机字符串),Session 负责保存私密信息。两者配合,既解决了 HTTP 无状态的问题,又保证了数据安全。
二、Cookie 的工作原理
识别返回用户包括三个步骤:
-
服务器发送 Cookie:服务器脚本向浏览器发送一组 Cookie,如姓名、年龄或识别号码。
-
浏览器存储 Cookie:浏览器将这些信息存储在本地计算机上,以备将来使用。
-
浏览器回传 Cookie:下一次浏览器向 Web 服务器发送请求时,会把这些 Cookie 信息发送到服务器,服务器使用这些信息来识别用户。
三、Django 中 Cookie 的操作
1. 设置 Cookie
python
rep.set_cookie(key, value, ...) rep.set_signed_cookie(key, value, salt='加密盐', ...)
常用参数:
| 参数 | 说明 |
|---|---|
key |
Cookie 的键名 |
value |
Cookie 的值 |
max_age |
过期时间(秒) |
expires |
过期日期 |
path |
Cookie 生效的路径,默认 / |
domain |
Cookie 生效的域名 |
secure |
是否仅 HTTPS 传输 |
httponly |
是否禁止 JavaScript 访问 |
2. 获取 Cookie
python
request.COOKIES.get(key)
3. 删除 Cookie
python
rep = HttpResponse() || render() || redirect() rep.delete_cookie(key)
注意: 必须先有响应对象(
rep),才能调用set_cookie或delete_cookie。
四、Cookie 实战:登录状态保持
1. 模型定义
python
class UserInfo(models.Model): username = models.CharField(max_length=32) password = models.CharField(max_length=64)
2. 路由配置
python
from django.contrib import admin from django.urls import path from cookie import views urlpatterns = [ path('admin/', admin.site.urls), path('login/', views.login), path('index/', views.index), path('logout/', views.logout), path('order/', views.order), ]
3. 视图函数
python
from django.shortcuts import render, redirect from cookie import models def login(request): if request.method == "GET": return render(request, "login.html") username = request.POST.get("username") password = request.POST.get("pwd") user_obj = models.UserInfo.objects.filter(username=username, password=password).first() if not user_obj: return redirect("/login/") else: rep = redirect("/index/") rep.set_cookie("is_login", True) # 设置 Cookie return rep def index(request): status = request.COOKIES.get('is_login') # 获取 Cookie if not status: return redirect('/login/') return render(request, "index.html") def logout(request): rep = redirect('/login/') rep.delete_cookie("is_login") # 删除 Cookie return rep def order(request): status = request.COOKIES.get('is_login') if not status: return redirect('/login/') return render(request, "order.html")
4. 模板文件
login.html:
html
<h3>用户登录</h3> <form action="" method="post"> {% csrf_token %} <p>用户名: <input type="text" name="username"></p> <p>密码: <input type="password" name="pwd"></p> <input type="submit"> </form>
index.html:
html
<h2>index 页面。。。</h2> <a href="/logout/">注销</a>
order.html:
html
<h2>order 页面。。。</h2> <a href="/logout/">注销</a>
流程说明: 登录成功后设置 is_login Cookie;访问 index 和 order 时检查该 Cookie;注销时删除 Cookie。
五、Session 的工作原理
Session 是保存在服务端的键值对。服务器在运行时可以为每一个用户的浏览器创建一个独享的 Session 对象。
1. 完整工作流程
Step 1: 浏览器第一次请求获取登录页面 login。
Step 2: 浏览器输入账号密码,第二次请求。若输入正确,服务器响应浏览器一个 index 页面和一个键为 sessionid、值为随机字符串的 Cookie,即 set_cookie("sessionid", 随机字符串)。
Step 3: 服务器内部在 django_session 表中记录一条数据:
| 字段 | 说明 |
|---|---|
session_key |
存的是随机字符串,即响应给浏览器的 Cookie 的 sessionid 键对应的值 |
session_data |
存的是用户的信息,即多个 request.session["key"]=value,且是密文 |
expire_date |
存的是该条记录的过期时间(默认 14 天) |
Step 4: 浏览器第三次请求其他资源时,携带 Cookie {sessionid: 随机字符串},服务器从 django_session 表中根据该随机字符串取出该用户的数据,供其使用(即保存状态)。
重要提醒:
django_session表中保存的是浏览器的信息,而不是每一个用户的信息。因此,同一浏览器多个用户请求只保存一条记录(后面覆盖前面),多个浏览器请求才保存多条记录。
2. Session 与 Cookie 的配合
Cookie 弥补了 HTTP 无状态的不足,让服务器知道来的人是"谁"。但 Cookie 以文本形式保存在浏览器端,安全性较差 ,且最大只支持 4096 字节。
因此,最佳实践是:
-
Cookie 只存一个随机字符串(
sessionid),用于识别不同用户。 -
Session 保存私密信息以及超过 4096 字节的文本。
六、Django 中 Session 的操作
1. 设置 Session
python
request.session["key"] = value
执行步骤:
-
生成随机字符串。
-
把随机字符串和设置的键值对保存到
django_session表的session_key和session_data里。 -
设置 Cookie:
set_cookie("sessionid", 随机字符串)响应给浏览器。
2. 获取 Session
python
request.session.get('key')
执行步骤:
-
从 Cookie 中获取
sessionid键的值,即随机字符串。 -
根据随机字符串从
django_session表过滤出记录。 -
取出
session_data字段的数据。
3. 删除 Session
删除整条记录(包括 session_key、session_data、expire_date 三个字段):
python
request.session.flush()
删除 session_data 里的其中一组键值对:
python
del request.session["key"]
执行步骤:
-
从 Cookie 中获取
sessionid键的值,即随机字符串。 -
根据随机字符串从
django_session表过滤出记录。 -
删除过滤出来的记录。
七、Session 实战:登录状态保持
1. 路由配置
python
from session import views as session_views urlpatterns = [ path('session_login/', session_views.login), path('s_index/', session_views.s_index), path('s_logout/', session_views.s_logout), ]
2. 视图函数
python
from django.shortcuts import render, redirect from session import models def login(request): if request.method == "GET": return render(request, "login.html") username = request.POST.get("username") password = request.POST.get("pwd") user_obj = models.UserInfo.objects.filter(username=username, password=password).first() if not user_obj: return redirect("/session_login/") else: request.session['is_login'] = True request.session['user1'] = username return redirect("/s_index/") def s_index(request): status = request.session.get('is_login') if not status: return redirect('/session_login/') return render(request, "s_index.html") def s_logout(request): # del request.session["is_login"] # 删除 session_data 里的一组键值对 request.session.flush() # 删除整条记录 return redirect('/session_login/')
3. 模板文件
s_index.html:
html
<h2>session_index 页面。。。{{ request.session.user1 }}</h2> <a href="/s_logout/">注销</a>
要点: 模板中可直接通过 {``{ request.session.user1 }} 访问 Session 数据(需启用 request 上下文处理器)。
八、Session 配置项
在 settings.py 中可以配置 Session 的行为:
| 配置项 | 默认值 | 说明 |
|---|---|---|
SESSION_ENGINE |
django.contrib.sessions.backends.db |
Session 存储引擎(数据库/缓存/文件) |
SESSION_COOKIE_NAME |
sessionid |
Cookie 中 Session 的键名 |
SESSION_COOKIE_AGE |
1209600(14 天) |
Session 过期时间(秒) |
SESSION_EXPIRE_AT_BROWSER_CLOSE |
False |
浏览器关闭时是否失效 |
SESSION_SAVE_EVERY_REQUEST |
False |
每次请求是否保存 Session |
常用配置示例:
python
SESSION_COOKIE_AGE = 60 * 60 * 24 * 7 # 7 天过期 SESSION_EXPIRE_AT_BROWSER_CLOSE = True # 关闭浏览器即失效
Session 存储引擎选择:
| 引擎 | 说明 |
|---|---|
db |
数据库(默认) |
cache |
缓存 |
cache_db |
缓存 + 数据库 |
file |
文件 |
signed_cookies |
加密 Cookie |
九、Cookie vs Session 对比
| 对比项 | Cookie | Session |
|---|---|---|
| 存储位置 | 客户端浏览器 | 服务器端 |
| 安全性 | 较低(可被查看/篡改) | 较高 |
| 容量限制 | 约 4096 字节 | 无明确限制 |
| 服务器压力 | 无 | 有(需存储) |
| 过期控制 | 由客户端控制 | 由服务器控制 |
| 典型用途 | 记住用户名、主题偏好 | 登录状态、购物车 |
最佳实践: 敏感数据存 Session,非敏感的小数据存 Cookie。Session 依赖 Cookie 传递 sessionid,两者配合使用。
十、状态管理流程图
十一、常见问题排查
| 问题现象 | 可能原因 | 解决方案 |
|---|---|---|
| Cookie 设置不生效 | 响应对象不对 | 确保用 rep.set_cookie(),且返回 rep |
| 刷新后登录状态丢失 | Cookie 被清除或过期 | 检查 max_age 和浏览器设置 |
| Session 数据取不到 | Session 中间件未启用 | 检查 MIDDLEWARE 中的 SessionMiddleware |
django_session 表不存在 |
未执行迁移 | 执行 python manage.py migrate |
| 同一浏览器多用户冲突 | Session 表按浏览器记录 | 属正常现象,不同浏览器互不干扰 |
模板中 request.session 取不到 |
上下文处理器未配置 | 检查 TEMPLATES 的 context_processors |
十二、小结
本篇系统讲解了 Django 中 Cookie 与 Session 的核心内容:
-
Cookie :存储在客户端的文本,通过
set_cookie、COOKIES.get、delete_cookie操作。 -
Session :存储在服务端的键值对,底层依赖 Cookie 传递
sessionid。 -
工作原理:Cookie 存随机字符串识别用户,Session 存私密数据。
-
常用操作 :
request.session["key"]=value设置,get()获取,flush()删除整条记录。 -
配置项 :
SESSION_COOKIE_AGE、SESSION_ENGINE等可自定义行为。
掌握 Cookie 与 Session 后,你已经理解了 Web 状态管理的底层机制。下一篇我们将学习 Django 的中间件(Middleware),深入请求与响应的处理管道。