Django入门教程(十六):Cookie与Session详解——用户状态管理的底层原理与实战

HTTP 是一种无状态协议。这意味着每次客户端检索网页时,客户端打开一个单独的连接到 Web 服务器,服务器会自动不保留之前客户端请求的任何记录。

问题: 用户登录后,下一次请求时服务器如何知道"来的人是谁"?

解决: 使用 Cookie 与 Session 来维持客户端与服务器之间的会话状态。

技术 存储位置 安全性 容量限制
Cookie 客户端浏览器 较低(明文文本) 约 4096 字节
Session 服务器端 较高 无明确限制

核心思路: Cookie 负责识别用户(存一个随机字符串),Session 负责保存私密信息。两者配合,既解决了 HTTP 无状态的问题,又保证了数据安全。

二、Cookie 的工作原理

识别返回用户包括三个步骤:

  1. 服务器发送 Cookie:服务器脚本向浏览器发送一组 Cookie,如姓名、年龄或识别号码。

  2. 浏览器存储 Cookie:浏览器将这些信息存储在本地计算机上,以备将来使用。

  3. 浏览器回传 Cookie:下一次浏览器向 Web 服务器发送请求时,会把这些 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 访问

python

复制代码
request.COOKIES.get(key)

python

复制代码
rep = HttpResponse() || render() || redirect()
rep.delete_cookie(key)

注意: 必须先有响应对象(rep),才能调用 set_cookiedelete_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;访问 indexorder 时检查该 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 表中保存的是浏览器的信息,而不是每一个用户的信息。因此,同一浏览器多个用户请求只保存一条记录(后面覆盖前面),多个浏览器请求才保存多条记录。

Cookie 弥补了 HTTP 无状态的不足,让服务器知道来的人是"谁"。但 Cookie 以文本形式保存在浏览器端,安全性较差 ,且最大只支持 4096 字节

因此,最佳实践是:

  • Cookie 只存一个随机字符串(sessionid),用于识别不同用户。

  • Session 保存私密信息以及超过 4096 字节的文本。

六、Django 中 Session 的操作
1. 设置 Session

python

复制代码
request.session["key"] = value

执行步骤:

  1. 生成随机字符串。

  2. 把随机字符串和设置的键值对保存到 django_session 表的 session_keysession_data 里。

  3. 设置 Cookie:set_cookie("sessionid", 随机字符串) 响应给浏览器。

2. 获取 Session

python

复制代码
request.session.get('key')

执行步骤:

  1. 从 Cookie 中获取 sessionid 键的值,即随机字符串。

  2. 根据随机字符串从 django_session 表过滤出记录。

  3. 取出 session_data 字段的数据。

3. 删除 Session

删除整条记录(包括 session_key、session_data、expire_date 三个字段):

python

复制代码
request.session.flush()

删除 session_data 里的其中一组键值对:

python

复制代码
del request.session["key"]

执行步骤:

  1. 从 Cookie 中获取 sessionid 键的值,即随机字符串。

  2. 根据随机字符串从 django_session 表过滤出记录。

  3. 删除过滤出来的记录。

七、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 取不到 上下文处理器未配置 检查 TEMPLATEScontext_processors
十二、小结

本篇系统讲解了 Django 中 Cookie 与 Session 的核心内容:

  • Cookie :存储在客户端的文本,通过 set_cookieCOOKIES.getdelete_cookie 操作。

  • Session :存储在服务端的键值对,底层依赖 Cookie 传递 sessionid

  • 工作原理:Cookie 存随机字符串识别用户,Session 存私密数据。

  • 常用操作request.session["key"]=value 设置,get() 获取,flush() 删除整条记录。

  • 配置项SESSION_COOKIE_AGESESSION_ENGINE 等可自定义行为。

掌握 Cookie 与 Session 后,你已经理解了 Web 状态管理的底层机制。下一篇我们将学习 Django 的中间件(Middleware),深入请求与响应的处理管道。

相关推荐
IT毕设实战小研5 小时前
基于大数据的商场商铺数据分析与可视化的设计与实现
android·java·大数据·django·课程设计
troy12821 小时前
Python 基础语法(九):Django/Flask/FastAPI 三大 Web 框架详细对比解析
python·jupyter·django·flask·github·fastapi
高洁011 天前
大模型的幻觉怎么治
人工智能·深度学习·django·transformer·tornado
新时代牛马1 天前
容器里拿到root 就等于宿主机沦陷?Capability、seccomp、AppArmor与user ns 讲透
django
言乐61 天前
Python:用AES-GCM算法加密链接内容,并生成可分享的加密链接和解密工具
python·django·virtualenv·pygame·tornado
典典分享指南2 天前
用飞书 Wiki 搭内容作战室:从零搭建团队内容协作中枢
django·flask·numpy·pyqt
言乐62 天前
Python + NumPy 从零实现的 BP 神经网络(反向传播)脚本模型,包含前向传播、反向传播、训练和预测,并用 XOR 数据做示例
python·django·virtualenv·pygame·tornado
高级程序源2 天前
django校企合作实习基地管理系统82506-计算机课程设计、毕业设计
vue.js·后端·python·mysql·django·课程设计·pygame
weixin_BYSJ19873 天前
【计算机毕设】基于SpringBoot与Vue的文物保护档案管理系统08621
vue.js·spring boot·spring cloud·微服务·架构·django·课程设计