在 Django 中,Cookie 和 Session 是实现用户状态跟踪的两大核心工具。它们协同工作,让服务器能“记住”你,从而提供连贯的浏览体验。

🍪 什么是 Cookie?

Cookie 是服务器发送到用户浏览器并保存在本地的一小段文本数据。它就像一张**“临时身份证”**,浏览器在每次请求时都会自动携带它,方便服务器识别。

在 Django 中,通过 HttpResponse 对象来操作 Cookie:

  • 设置 Cookie:使用 set_cookie() 方法。

    from django.http import HttpResponse
    
    def set_cookie_view(request):
        response = HttpResponse("Cookie 已设置")
        # 设置一个名为 'user_name',值为 'John' 的 Cookie,有效期为 7 天
        response.set_cookie('user_name', 'John', max_age=60*60*24*7) 
        return response
    

    set_cookie() 可以接收 max_age(秒数)或 expires(具体日期时间)参数来控制有效期。不设置的话,默认在浏览器关闭时失效。

  • 获取 Cookie:通过 request.COOKIES 字典获取。

    def get_cookie_view(request):
        user_name = request.COOKIES.get('user_name', 'Guest') # 如果没有则返回 'Guest'
        return HttpResponse(f"Hello, {user_name}!")
    
  • 删除 Cookie:使用 delete_cookie() 方法。

    def delete_cookie_view(request):
        response = HttpResponse("Cookie 已删除")
        response.delete_cookie('user_name')
        return response
    

注意:Cookie 存储在客户端,大小限制在 4KB 左右,且敏感信息有被篡改和泄露的风险。

🔑 什么是 Session?

由于 Cookie 存在安全风险且存储量小,Session 机制应运而生。Session 的数据存储在服务器端(如数据库或缓存中),而客户端只保存一个用来在服务器上查找数据的**“取件码”,即 sessionid。它就像一个“保险柜”**,安全地存放着用户的敏感数据。

Django 的 Session 框架默认是启用的。其数据默认存储在数据库中。使用前需要确保 'django.contrib.sessions'INSTALLED_APPS 中,并执行 migrate 来创建数据表。

在 Django 中操作 Session 非常直观,就像一个字典:

  • 设置 Session 数据

    def set_session_view(request):
        # 存储数据,键为 'user_id',值为 123
        request.session['user_id'] = 123
        # 存储更复杂的数据也是可以的
        request.session['cart_items'] = ['item1', 'item2']
        return HttpResponse("Session 数据已设置")
    
  • 获取 Session 数据

    def get_session_view(request):
        user_id = request.session.get('user_id', None)
        return HttpResponse(f"User ID from session: {user_id}")
    
  • 删除 Session 数据

    def delete_session_view(request):
        # 删除单个键
        del request.session['user_id'] 
        # 或者清除整个会话
        # request.session.flush() 
        return HttpResponse("Session 数据已删除")
    

你可以在 settings.py 中通过 SESSION_ENGINE 配置 Session 的存储方式:

  • 数据库(默认)"django.contrib.sessions.backends.db"
  • 缓存"django.contrib.sessions.backends.cache"
  • 文件"django.contrib.sessions.backends.file"
  • 缓存+数据库"django.contrib.sessions.backends.cached_db"
  • 基于Cookie"django.contrib.sessions.backends.signed_cookies"

重要request.session 属性在视图函数的第一个参数 request 中即可获得。

🤝 Cookie 与 Session 的协作流程

  1. 用户首次访问:Django 创建一个新的 Session(生成一个唯一的 sessionid),并通过 Set-Cookie 响应头将 sessionid 以 Cookie 的形式发送给浏览器。
  2. 用户后续请求:浏览器在请求头中自动携带 sessionid 这个 Cookie。
  3. 服务器验证:Django 根据接收到的 sessionid,在服务器端(数据库/缓存)查找对应的 Session 数据。
  4. 数据处理:视图函数就可以通过 request.session 来读写属于该用户的数据了。

⚖️ Cookie 与 Session 的区别总结

特性 Cookie Session
存储位置 客户端(浏览器) 服务端(数据库/缓存/文件)
安全性 较低,数据可见且可被用户篡改 较高,数据存储在服务器,相对安全
存储大小 有限制(约4KB) 理论上无限制,取决于服务器配置
数据类型 只能存储字符串 可以存储任意 Python 对象(字典、列表等)
典型用途 保存用户偏好、跟踪ID等非敏感信息 保存登录状态、购物车等敏感或临时数据

💡 最佳实践与建议

  • 敏感数据用 Session:永远不要将密码、信用卡号等敏感信息存储在 Cookie 中,请使用 Session。
  • 非敏感数据用 Cookie:对于用户的语言偏好、主题选择等不敏感且希望长期保存的数据,使用 Cookie 更合适。
  • 安全配置(重要)
    • 设置 SECURE_COOKIE:在生产环境中,务必设置 SESSION_COOKIE_SECURE = TrueCSRF_COOKIE_SECURE = True,确保 Cookie 仅通过 HTTPS 传输。
    • 设置 HTTPONLY:设置 SESSION_COOKIE_HTTPONLY = True,防止客户端的 JavaScript 脚本访问 Session Cookie,有效防御 XSS 攻击。
  • 控制 Session 过期时间
    • 设置 SESSION_EXPIRE_AT_BROWSER_CLOSE = True,让 Session 在浏览器关闭时过期。
    • 设置 SESSION_COOKIE_AGE(单位:秒)来控制 Session 的绝对过期时间。
    • 也可以对单个 Session 使用 request.session.set_expiry(value) 进行精细控制。

总而言之,Cookie 是客户端的“身份证”,用于标识身份;而 Session 是服务端的“档案柜”,用于安全地存储用户数据。在 Django 中,通过 Session 框架,你可以非常方便和安全地管理用户的状态。


我们来实现一个迷你用户中心,功能包括:

  • Session 保存登录状态(用户ID)
  • Cookie 记住用户选择的主题颜色(亮色/暗色)
  • 登录后才能访问个人主页,未登录跳转回登录页

这是一个非常典型的组合应用场景,让你直观感受它们如何协作。


🚀 项目准备(省略创建项目/应用步骤)

假设你已创建 Django 项目 myproject 和应用 myapp,并在 settings.py 中添加了 'myapp',且执行了 migrate(Django 默认 Session 依赖数据库表)。

📝 视图函数 (views.py)

from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import render
from django.urls import reverse

# ---------- 登录(使用 Session) ----------
def login_view(request):
    # 如果是 POST 请求,进行“验证”
    if request.method == 'POST':
        username = request.POST.get('username')
        password = request.POST.get('password')

        # 简单演示,硬编码验证(实际项目中请用 User 模型)
        if username == 'admin' and password == '123456':
            # 登录成功:将用户 ID(或用户名)存入 Session
            request.session['user_id'] = 1   # 假设用户 ID 为 1
            request.session['username'] = username
            # 重定向到个人主页
            return HttpResponseRedirect(reverse('profile'))
        else:
            return HttpResponse("用户名或密码错误,请<a href='/login/'>重试</a>")

    # GET 请求显示登录表单
    return render(request, 'login.html')

# ---------- 个人主页(需要登录) ----------
def profile_view(request):
    # 检查 Session 中是否有 user_id
    if not request.session.get('user_id'):
        # 未登录则跳转到登录页
        return HttpResponseRedirect(reverse('login'))

    # 获取用户名(从 Session)
    username = request.session.get('username', '用户')

    # 获取主题偏好(从 Cookie,默认为 'light')
    theme = request.COOKIES.get('theme', 'light')

    context = {
        'username': username,
        'theme': theme,
    }
    return render(request, 'profile.html', context)

# ---------- 登出(清除 Session) ----------
def logout_view(request):
    # 清除整个 Session(同时删除数据库记录)
    request.session.flush()
    # 也可以只删除某些键:del request.session['user_id']
    return HttpResponse("您已登出,<a href='/login/'>重新登录</a>")

# ---------- 切换主题(设置 Cookie) ----------
def set_theme_view(request):
    # 从 GET 参数获取主题值
    theme = request.GET.get('theme', 'light')   # 默认亮色
    # 创建重定向响应,回到个人主页
    response = HttpResponseRedirect(reverse('profile'))
    # 设置 Cookie,有效期 30 天
    response.set_cookie('theme', theme, max_age=60*60*24*30)
    return response

🌐 URL 配置 (urls.py)

from django.urls import path
from . import views

urlpatterns = [
    path('login/', views.login_view, name='login'),
    path('profile/', views.profile_view, name='profile'),
    path('logout/', views.logout_view, name='logout'),
    path('set-theme/', views.set_theme_view, name='set_theme'),
]

🖼️ 模板文件

login.html(登录表单)

<!DOCTYPE html>
<html>
<head><title>登录</title></head>
<body>
    <h2>登录</h2>
    <form method="post">
        {% csrf_token %}
        用户名: <input type="text" name="username"><br>
        密码: <input type="password" name="password"><br>
        <button type="submit">登录</button>
    </form>
</body>
</html>

profile.html(个人主页)

<!DOCTYPE html>
<html>
<head>
    <title>个人主页</title>
    <style>
        body {
            background-color: {% if theme == 'dark' %} #222 {% else %} #fff {% endif %};
            color: {% if theme == 'dark' %} #eee {% else %} #000 {% endif %};
        }
    </style>
</head>
<body>
    <h1>欢迎, {{ username }} !</h1>
    <p>当前主题: {{ theme }}</p>
    <p>
        <a href="{% url 'set_theme' %}?theme=light">🌞 亮色主题</a> |
        <a href="{% url 'set_theme' %}?theme=dark">🌙 暗色主题</a>
    </p>
    <p><a href="{% url 'logout' %}">登出</a></p>
</body>
</html>

🔄 运行流程演示

  1. 首次访问 /login/ → 显示登录表单。
  2. 输入 admin / 123456 → 后端验证通过,执行 request.session['user_id'] = 1,Django 自动在响应头中设置 Set-Cookie: sessionid=...,浏览器保存这个 Cookie。
  3. 重定向到 /profile/ → 视图检查 request.session.get('user_id') 存在,渲染主页,同时从 request.COOKIES 中读取 theme(如果没有,默认为 light)。
  4. 点击“暗色主题” → 访问 /set-theme/?theme=dark → 视图设置 response.set_cookie('theme', 'dark'),然后重定向回 /profile/。此时浏览器将 theme=dark 保存为 Cookie。
  5. 刷新 /profile/ → 视图从 Cookie 中读到的 theme 就是 dark,页面背景变暗。
  6. 点击“登出” → 调用 request.session.flush(),删除服务端 Session 记录,并返回登出信息。此时浏览器的 sessionid Cookie 虽然还在,但服务端已无对应数据,下次访问 /profile/ 会被跳转到登录页。

🛡️ 安全小贴士(生产环境必看)

  • settings.py 中务必设置
    SESSION_COOKIE_SECURE = True     # 仅 HTTPS 传输
    SESSION_COOKIE_HTTPONLY = True   # 禁止 JavaScript 读取 sessionid
    CSRF_COOKIE_SECURE = True        # 同样适用于 CSRF 令牌
    
  • 登录验证:上面的例子是硬编码,实际请使用 Django 内置的 authenticate()login() 方法,它们会自动处理 Session。
  • Session 过期:可在 settings.py 中配置 SESSION_COOKIE_AGE(秒)或 SESSION_EXPIRE_AT_BROWSER_CLOSE = True

📦 总结

  • Session 用于存储用户登录状态(user_id),数据在服务端,安全可靠。
  • Cookie 用于存储用户主题偏好(theme),数据在客户端,轻量且无需服务器资源。
  • 两者配合:Cookie 携带身份标识(sessionid)和个性化选项(theme),Session 保存具体用户数据,各自发挥优势。

你可以把这段代码跑起来,亲手体验一下——登录、切换主题、登出,看看 Cookie 和 Session 在浏览器开发者工具里的变化,理解会更深刻!如果还有疑问,随时问我。😊

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐