Django cookie 与 session(长文讲解)

更新时间:

💡一则或许对你有用的小广告

欢迎加入小哈的星球 ,你将获得:专属的项目实战 / 1v1 提问 / Java 学习路线 / 学习打卡 / 每月赠书 / 社群讨论

  • 新项目:《从零手撸:仿小红书(微服务架构)》 正在持续爆肝中,基于 Spring Cloud Alibaba + Spring Boot 3.x + JDK 17...点击查看项目介绍 ;
  • 《从零手撸:前后端分离博客项目(全栈开发)》 2 期已完结,演示链接: http://116.62.199.48/ ;

截止目前, 星球 内专栏累计输出 82w+ 字,讲解图 3441+ 张,还在持续爆肝中.. 后续还会上新更多项目,目标是将 Java 领域典型的项目都整一波,如秒杀系统, 在线商城, IM 即时通讯,权限管理,Spring Cloud Alibaba 微服务等等,已有 2900+ 小伙伴加入学习 ,欢迎点击围观

前言

在 Web 开发中,保持用户状态是一项核心需求。无论是记录登录状态、购物车内容,还是个性化设置,都需要一种机制来跟踪用户的行为。Django 提供了 CookieSession 两种工具,它们分别以不同的方式实现这一目标。对于编程初学者和中级开发者而言,理解两者的区别、原理以及应用场景,能显著提升开发效率与代码质量。本文将通过概念解析、代码示例和实际案例,系统性地讲解 Django 中 Cookie 与 Session 的使用方法与最佳实践。


一、Cookie 与 Session 的基础概念

1.1 Cookie:客户端的“记忆卡片”

Cookie 是由服务器发送到客户端(如浏览器)的一小段文本信息,存储在用户设备中。当客户端再次访问同一域名时,会自动将 Cookie 信息发送回服务器,从而帮助服务器识别用户身份。

形象比喻
可以将 Cookie 想象成一家餐馆的菜单。当你第一次进入餐馆时,服务员会递给你一份菜单(即服务器发送 Cookie)。后续每次点餐时,你只需展示这份菜单(携带 Cookie),服务员就能知道你的偏好或历史订单。

核心特性

  • 存储位置:客户端(如浏览器);
  • 生命周期:可设置过期时间,默认为浏览器会话结束时失效;
  • 用途:轻量级存储,适合存储少量不敏感的数据(如主题偏好、语言设置)。

1.2 Session:服务器的“记忆簿”

Session 是一种服务器端的存储机制,用于在用户多次请求之间保持状态。服务器会为每个用户生成一个唯一的 Session ID,并通过 Cookie 将其发送给客户端。客户端后续请求时携带该 Cookie,服务器通过 Session ID 在服务端查找对应的存储数据。

形象比喻
Session 像是服务员为每位顾客准备的专属记事本。服务员(服务器)通过桌号(Session ID)找到顾客的记事本,记录其点餐偏好、消费历史等信息。即使顾客暂时离开,服务员仍能通过桌号快速恢复服务。

核心特性

  • 存储位置:服务器端(如数据库、缓存);
  • 生命周期:默认为浏览器会话结束或手动设置过期时间;
  • 用途:安全存储敏感数据(如用户登录状态、购物车内容)。

1.3 两者的核心区别

特性CookieSession
存储位置客户端(浏览器)服务器端(如数据库或内存)
数据安全性客户端可读写,需加密敏感数据数据在服务器端,相对更安全
存储容量单个 Cookie 通常不超过 4KB受服务器存储能力限制,容量更大
适用场景简单状态记录(如主题、语言)需要持久化、安全的状态管理

二、Django 中 Cookie 的实现与配置

2.1 Cookie 的基本操作

Django 提供了直接操作 Cookie 的接口,开发者可通过 request.COOKIES 读取 Cookie,通过 response.set_cookie() 设置 Cookie。

示例:设置与读取 Cookie

from django.http import HttpResponse

def set_cookie(request):
    response = HttpResponse("Cookie 设置成功!")
    response.set_cookie('username', 'Alice', max_age=3600)  # 有效期 1 小时
    return response

def get_cookie(request):
    username = request.COOKIES.get('username', '未设置')
    return HttpResponse(f"当前用户名为:{username}")

注意事项

  • 安全设置
    通过 secure=Truehttponly=True 参数,可强制 Cookie 仅通过 HTTPS 传输,并防止 JavaScript 直接访问,降低 XSS 攻击风险。
  • 加密处理
    若 Cookie 需存储敏感信息(如用户 ID),建议使用 Django 的 get_signed_cookie 方法,结合 django.core.signing 模块进行加密:
    from django.http import HttpResponse
    from django.core.signing import sign, unsign
    
    def set_secure_cookie(request):
        user_id = 123
        signed_value = sign(user_id)
        response = HttpResponse("加密 Cookie 已设置")
        response.set_cookie('user_id', signed_value)
        return response
    
    def get_secure_cookie(request):
        signed_value = request.COOKIES.get('user_id')
        if signed_value:
            user_id = unsign(signed_value)
            return HttpResponse(f"解密后的用户 ID:{user_id}")
        return HttpResponse("未找到 Cookie")
    

2.2 全局 Cookie 配置

Django 的 settings.py 中提供了以下 Cookie 相关配置项:

SESSION_COOKIE_DOMAIN = '.example.com'

SESSION_COOKIE_AGE = 1209600  # 14 天

SESSION_COOKIE_SECURE = True

SESSION_COOKIE_HTTPONLY = True

三、Django Session 的实现与高级用法

3.1 Session 的基本原理

Django 的 Session 系统默认使用数据库存储 Session 数据。每个 Session 对象包含以下字段:

  • session_key:唯一标识符(如 a1s2d3f4g5h6j7k8);
  • session_data:经过 Base64 编码并加密的字典数据;
  • expire_date:过期时间。

示例:手动操作 Session

def login(request):
    # 设置 Session 数据
    request.session['is_authenticated'] = True
    request.session['user_id'] = 123
    return HttpResponse("登录成功!")

def check_login(request):
    is_authenticated = request.session.get('is_authenticated', False)
    if is_authenticated:
        return HttpResponse("已登录!")
    else:
        return HttpResponse("未登录,请先登录!")

3.2 Session 的存储后端

Django 支持多种 Session 存储后端,开发者可通过 SESSION_ENGINE 配置:

  • 数据库存储(默认):django.contrib.sessions.backends.db
  • 缓存存储django.contrib.sessions.backends.cache(适合高并发场景);
  • 文件存储django.contrib.sessions.backends.file
  • 缓存+数据库混合django.contrib.sessions.backends.cached_db

配置示例:使用缓存后端

SESSION_ENGINE = "django.contrib.sessions.backends.cache"
CACHES = {
    'default': {
        'BACKEND': 'django.core.cache.backends.redis.RedisCache',
        'LOCATION': 'redis://127.0.0.1:6379/1',
    }
}

3.3 Session 的高级技巧

3.3.1 临时 Session

若希望用户关闭浏览器后自动清除 Session,可设置 request.session.set_expiry(0)

3.3.2 Session 缓存刷新

在需要频繁读取 Session 数据时,可通过 request.session.modified = True 强制更新 Session,避免因缓存导致的数据不一致。

3.3.3 自定义 Session 数据结构

Session 可存储任意可序列化的 Python 对象(如字典、列表)。例如:

request.session['cart'] = {
    'product_id': 101,
    'quantity': 2,
    'price': 99.99
}

四、实战案例:实现用户登录状态管理

4.1 需求分析

构建一个简单的用户登录系统,要求:

  1. 用户登录后,通过 Session 保持登录状态;
  2. 未登录用户访问个人中心时跳转至登录页面;
  3. 提供退出登录功能,清除 Session。

4.2 实现步骤

4.2.1 创建模型与表单

from django.contrib.auth.models import AbstractUser

class CustomUser(AbstractUser):
    phone_number = models.CharField(max_length=15, unique=True)

from django import forms

class LoginForm(forms.Form):
    username = forms.CharField(max_length=150)
    password = forms.CharField(widget=forms.PasswordInput)

4.2.2 实现登录逻辑

from django.shortcuts import render, redirect
from django.contrib.auth import authenticate
from .forms import LoginForm

def login_view(request):
    if request.method == 'POST':
        form = LoginForm(request.POST)
        if form.is_valid():
            user = authenticate(
                username=form.cleaned_data['username'],
                password=form.cleaned_data['password']
            )
            if user is not None:
                # 设置 Session
                request.session['user_id'] = user.id
                request.session['is_authenticated'] = True
                return redirect('profile')
    else:
        form = LoginForm()
    return render(request, 'login.html', {'form': form})

4.2.3 保护个人中心页面

from django.http import HttpResponseForbidden

def profile(request):
    if not request.session.get('is_authenticated', False):
        return HttpResponseForbidden("请先登录!")
    user_id = request.session['user_id']
    # 查询用户数据并渲染页面
    return render(request, 'profile.html', {'user_id': user_id})

4.2.4 退出登录

def logout(request):
    # 清除 Session
    request.session.flush()
    return redirect('login')

五、性能优化与安全建议

5.1 Session 性能优化

  • 使用缓存存储:对于高并发场景,优先选择 cached_db 或纯缓存后端;
  • 减少 Session 写入频率:通过 request.session.modified 控制更新时机,降低 I/O 开销。

5.2 安全加固措施

  • 启用 HTTPS:确保 Cookie 通过加密通道传输;
  • 禁用 Session 固定攻击:在用户登录后,调用 request.session.cycle_key() 重新生成 Session ID;
  • 设置合理的 Session 过期时间:平衡用户体验与安全需求(如 2 小时自动过期)。

六、总结

本文系统性地讲解了 Django 中 Cookie 与 Session 的核心概念、实现方法及实战案例。通过对比两者的存储位置、安全性与适用场景,开发者能更灵活地选择工具。在实际开发中,Cookie 适合轻量级状态管理,而 Session 则是处理敏感数据或复杂状态的最佳选择。

建议读者通过以下方式进一步巩固知识:

  1. 实现一个基于 Session 的购物车系统;
  2. 探索 Django 的 django-session-security 插件,增强 Session 安全性;
  3. 对比其他框架(如 Flask)的 Cookie/Session 实现,拓宽技术视野。

掌握 Django 的 Cookie 与 Session 管理,是构建健壮 Web 应用的重要基石,希望本文能为你的开发之路提供清晰的指引。

最新发布