Django - Session 管理
Django - 会话 (Sessions)
Section titled “Django - 会话 (Sessions)”虽然 Cookie 允许在客户端存储数据,但 Session 提供了一种在 服务器端 存储用户特定数据的机制。对于敏感信息而言,这种方式通常更安全,因为实际数据不驻留在用户的浏览器中。
Session 工作原理:
- 当用户首次访问使用 Session 的网站时,Django 会生成一个唯一的、随机的 会话 ID (Session ID)。
- Django 将此 Session ID 发送回用户的浏览器,通常存储在一个标准的 Cookie 中。
- 在同一用户的后续请求中,浏览器会将 Session ID Cookie 发送回 Django。
- Django 使用此 ID 在服务器端查找对应的 Session 数据(例如,在数据库、缓存或文件系统中)。
- 应用程序随后可以读取或写入与该特定用户 Session 相关的数据。
通过这种方式,客户端只存储了 Session ID;实际的 Session 数据(如用户 ID、购物车内容、用户偏好设置)仍然保留在服务器上。
启用 Session
Section titled “启用 Session”在用 django-admin startproject 创建的新项目中,Django 的 Session 框架默认是启用的。它依赖于特定的中间件 (middleware) 和一个在 settings.py 中列出的应用 (app):
- 中间件 (Middleware): 确保
'django.contrib.sessions.middleware.SessionMiddleware'存在于您的MIDDLEWARE设置中(通常放置在UpdateCacheMiddleware之后,如果使用站点范围缓存,则放置在CommonMiddleware之前,否则其确切位置不太关键,但通常在列表中间)。
MIDDLEWARE = [ # ... 'django.contrib.sessions.middleware.SessionMiddleware', # ...]- 已安装应用 (Installed App): 确保
'django.contrib.sessions'存在于您的INSTALLED_APPS设置中。
INSTALLED_APPS = [ # ... 'django.contrib.sessions', # ...]- 数据库迁移 (Database Migrations): 如果您使用的是默认的基于数据库的 Session,则需要运行迁移 (migrate) 来创建必要的表 (
django_session)。
python manage.py migrate配置 Session 引擎
Section titled “配置 Session 引擎”默认情况下,Django 将 Session 数据存储在数据库中(django_session 表)。您可以通过在 settings.py 中使用 SESSION_ENGINE 设置来改变此行为:
'django.contrib.sessions.backends.db': 数据库(默认)。可靠,但在高负载下可能较慢。'django.contrib.sessions.backends.cache': 使用您的默认缓存后端 (cache backend)。更快,但如果缓存被清除,数据可能会丢失。'django.contrib.sessions.backends.cached_db': 同时写入数据库和缓存(写穿透缓存)。先从缓存读取,然后从数据库读取。一个很好的平衡。'django.contrib.sessions.backends.file': 将 Session 存储在指定目录 (SESSION_FILE_PATH) 的文件中。'django.contrib.sessions.backends.signed_cookies': 将所有 Session 数据直接存储在客户端 Cookie 中,经过加密签名。避免了服务器端存储的需求,但受限于 Cookie 大小,且如果签名密钥被泄露,存在潜在的安全隐患。
示例:使用缓存支持的 Session
SESSION_ENGINE = 'django.contrib.sessions.backends.cache'在视图中使用 Session
Section titled “在视图中使用 Session”当 Session 中间件激活时,每个 HttpRequest 对象(视图函数中的第一个参数,通常命名为 request)都将拥有一个 session 属性。此属性的行为类似于 Python 字典。
让我们修改 Cookies 一章中的简单登录示例来使用 Session。
from django.shortcuts import render, redirectfrom django.http import HttpResponsefrom .forms import LoginForm # 假设存在 LoginFormfrom datetime import datetime # 导入 datetime 模块
def login_session_view(request): if request.method == 'POST': form = LoginForm(request.POST) if form.is_valid(): username = form.cleaned_data['username'] # 将用户名存储到 Session 中 request.session['username'] = username request.session['login_time'] = str(datetime.now()) # 存储登录时间
# 设置 Session 过期时间(例如,30 分钟不活动后过期) request.session.set_expiry(1800)
return redirect('session_status') # 重定向到状态页 else: return render(request, 'login.html', {'form': form}) else: form = LoginForm() return render(request, 'login.html', {'form': form})
def session_status_view(request): # 使用 .get() 安全地访问 Session 数据 username = request.session.get('username')
if username: # 用户已通过 Session 登录 login_time = request.session.get('login_time', 'N/A') expiry_age = request.session.get_expiry_age() return render(request, 'loggedin.html', { 'username': username, 'login_time': login_time, 'expiry_seconds': expiry_age }) else: # 没有活动的 Session 或用户名未设置 return redirect('login_session') # 重定向回登录页
def logout_session_view(request): # 完全清除 Session 数据 request.session.flush() return render(request, 'logout_message.html')
# 在 myapp/urls.py 中添加 URL 模式:# path('login/', views.login_session_view, name='login_session')# path('status/', views.session_status_view, name='session_status')# path('logout/', views.logout_session_view, name='logout_session')关键 Session 操作:
- 存储数据:
request.session['my_key'] = 'my_value' - 检索数据:
value = request.session.get('my_key', 'default_if_not_found')(使用.get()比request.session['my_key']更安全) - 删除数据:
del request.session['my_key'](如果键不存在会引发KeyError) - 检查是否存在:
'my_key' in request.session - 清除所有 Session 数据:
request.session.flush()(相当于注销用户) - 设置过期时间:
request.session.set_expiry(value),其中value可以是秒数(整数)、datetime对象,或者 0(浏览器关闭时过期),或者None(使用全局设置)。 - 获取过期信息:
request.session.get_expiry_age()(剩余秒数),request.session.get_expiry_date()(datetime 对象)。 - 检查是否设置浏览器关闭过期:
request.session.get_expire_at_browser_close()(返回True或False)。
Session 设置
Section titled “Session 设置”您可以通过 settings.py 中的设置控制全局 Session 行为:
SESSION_COOKIE_AGE:Session Cookie 的默认生存期,以秒为单位(例如,1209600表示 2 周)。SESSION_COOKIE_HTTPONLY:设为True(默认)以防止客户端 JavaScript 访问 Session Cookie。SESSION_COOKIE_SECURE:如果您的网站只使用 HTTPS,则设为True。SESSION_COOKIE_SAMESITE:控制跨站点 Cookie 行为(默认是 ‘Lax’,选项还有 ‘Strict’ 或 ‘None’)。SESSION_EXPIRE_AT_BROWSER_CLOSE:如果您希望 Session 在浏览器关闭时过期,则设为True(会覆盖SESSION_COOKIE_AGE)。SESSION_SAVE_EVERY_REQUEST:如果为True,则在每次请求时都会保存 Session,即使它未修改。默认是False(仅在 Session 数据更改时保存),这样更高效。
Session 是在 Django 中构建有状态 Web 应用的基础,尤其对于处理用户认证和个性化体验至关重要。
进一步阅读:
- Django Session 文档:https://docs.djangoproject.com/en/stable/topics/http/sessions/