Django - Cookies 处理
Django - 处理 Cookies
Section titled “Django - 处理 Cookies”HTTP 是一种无状态协议,这意味着每个请求都是独立的。Cookie 是网站存储在用户浏览器上的一小段数据。它们允许 Web 应用程序在多个请求中记住关于用户的信息,从而本质上增加了状态。
Cookie 的常见用途包括:
- 会话管理(跟踪已登录用户)。Django 的 session 框架通常会自动处理此问题。
- 个性化设置(记住用户偏好,如主题或语言)。
- 跟踪(分析用户行为,尽管这方面存在重要的隐私问题)。
重要注意事项:
- 客户端存储: Cookie 存储在用户计算机上,这可能对敏感数据不安全。
- 用户控制: 用户可以配置其浏览器以阻止 Cookie 或删除 Cookie。
- 大小限制: 浏览器对每个域名的 Cookie 数量和大小施加限制。
- 安全性: 适当使用
HttpOnly和Secure标志以及SameSite属性来缓解跨站脚本(XSS)和跨站请求伪造(CSRF)等风险。 - 隐私法规: 注意 GDPR 和 CCPA 等关于 Cookie 使用和同意的法规。
在 Django 中设置 Cookie
Section titled “在 Django 中设置 Cookie”Cookie 在视图返回 之前 设置在 HttpResponse 对象上。你使用 response.set_cookie() 方法。
让我们修改一个假设的登录视图,以便设置一个 Cookie 来记住用户的偏好主题。
from django.shortcuts import render, redirectfrom django.http import HttpResponsefrom .forms import LoginForm # Assuming you have a LoginForm defined# 假设你定义了一个 LoginFormimport datetime
def login_view(request): if request.method == 'POST': form = LoginForm(request.POST) if form.is_valid(): username = form.cleaned_data['username'] # Simulate successful login # 模拟成功登录 # ... (authentication logic would go here) # ... (认证逻辑在这里)
# Create a response object (e.g., redirect to dashboard) # 创建一个响应对象(例如,重定向到 dashboard) response = redirect('dashboard') # Assuming 'dashboard' is a named URL # 假设 'dashboard' 是一个命名的 URL
# Set a cookie for theme preference # 设置一个用于主题偏好的 cookie theme = request.POST.get('theme', 'light') # Get theme from form or default # 从表单获取主题或使用默认值 response.set_cookie( key='user_theme', value=theme, max_age=60*60*24*30, # Expires in 30 days (in seconds) # 30 天后过期(以秒为单位) httponly=True, # Prevent JavaScript access (good for security) # 防止 JavaScript 访问(有利于安全) samesite='Lax' # Mitigate CSRF risk # 缓解 CSRF 风险 # secure=True # Uncomment if site uses HTTPS only # 如果网站只使用 HTTPS,请取消注释 )
# Set another cookie to remember login time # 设置另一个 cookie 来记住登录时间 response.set_cookie( 'last_login', str(datetime.datetime.now()), max_age=60*10 # Expires in 10 minutes # 10 分钟后过期 )
return response else: # Form is invalid, re-render login page with errors # 表单无效,重新渲染登录页面并显示错误 return render(request, 'login.html', {'form': form}) else: # GET request, show the login form # GET 请求,显示登录表单 form = LoginForm() return render(request, 'login.html', {'form': form})
# A simple dashboard view (target of redirect)# 一个简单的 dashboard 视图(重定向目标)def dashboard_view(request): return HttpResponse("Welcome to your dashboard!")set_cookie 的关键参数:
key:Cookie 的名称(字符串)。value:要存储的值(字符串)。非字符串值会自动转换。max_age:Cookie 的生命周期,以秒为单位。如果为None或省略,则它是会话 Cookie(浏览器关闭时删除)。expires:max_age的替代方案。接受datetime对象或格式化字符串。如果两者都设置,max_age优先。path:Cookie 有效的 URL 路径(默认为 ’/’)。domain:Cookie 有效的域名。secure:如果为True,则 Cookie 仅通过 HTTPS 发送。httponly:如果为True,则客户端 JavaScript 无法访问 Cookie(有助于防止 XSS 攻击)。samesite:控制跨站请求行为(‘Strict’、‘Lax’、‘None’)。有助于防止 CSRF 攻击。如果设置为 ‘None’,则需要secure=True。
在 Django 中读取 Cookie
Section titled “在 Django 中读取 Cookie”浏览器发送的 Cookie 可以在 request.COOKIES 这个类似字典的对象中获取。
让我们创建一个视图,读取之前设置的 user_theme Cookie。
from django.shortcuts import render
def display_preferences_view(request): # Use .get() for safe access - returns None if cookie doesn't exist # 使用 .get() 安全访问 - 如果 cookie 不存在则返回 None user_theme = request.COOKIES.get('user_theme', 'light') # Default to 'light' # 默认主题为 'light' last_login_str = request.COOKIES.get('last_login')
context = { 'current_theme': user_theme, 'last_login_time': last_login_str } return render(request, 'preferences.html', context)直接访问 request.COOKIES['cookie_name'] 如果 Cookie 不存在会引发 KeyError。使用 request.COOKIES.get('cookie_name', default_value) 更安全。
删除 Cookie
Section titled “删除 Cookie”要删除 Cookie,使用 response.delete_cookie() 方法。它的工作原理是将 Cookie 的过期日期设置为过去,并将 max_age 设置为 0。
from django.shortcuts import redirectfrom django.http import HttpResponse
def logout_view(request): # Perform logout actions (e.g., clear session data) # 执行注销操作(例如,清除会话数据) # ...
response = redirect('home') # Redirect to home page # 重定向到主页
# Delete the cookies we set earlier # 删除我们之前设置的 cookie response.delete_cookie('user_theme') response.delete_cookie('last_login')
return response
def home_view(request): return HttpResponse("Welcome home!") return HttpResponse("欢迎回家!")如果设置 Cookie 时使用了非默认的 path 和 domain 参数,则删除时必须传递相同的参数给 delete_cookie。
示例场景:简单的超时逻辑
Section titled “示例场景:简单的超时逻辑”让我们结合设置和读取 Cookie,实现一个基于 last_login Cookie 的简单超时逻辑(尽管 Django sessions 通常是更可靠、更安全的真实身份验证方式)。
import datetimefrom django.shortcuts import render, redirectfrom django.http import HttpResponse
TIMEOUT_SECONDS = 10 # Short timeout for demonstration# 短超时用于演示
def protected_page_view(request): last_login_str = request.COOKIES.get('last_login')
if last_login_str: try: # Attempt to parse the stored datetime string # 尝试解析存储的日期时间字符串 # Note: Storing timezone-aware datetimes is more robust # 注意:存储带时区的日期时间更健壮 last_login_time = datetime.datetime.strptime(last_login_str.split('.')[0], "%Y-%m-%d %H:%M:%S") time_difference = datetime.datetime.now() - last_login_time
if time_difference.total_seconds() < TIMEOUT_SECONDS: # Still within the allowed time # 仍在允许的时间范围内 return render(request, 'protected_page.html', {'message': 'Welcome back!'}) return render(request, 'protected_page.html', {'message': '欢迎回来!'}) else: # Timeout expired # 超时已过期 response = redirect('login') # Redirect to login # 重定向到登录页 response.delete_cookie('last_login') # Clear the expired cookie # 清除过期的 cookie return response except (ValueError, TypeError): # Handle cases where the cookie value is invalid # 处理 cookie 值无效的情况 response = redirect('login') response.delete_cookie('last_login') return response else: # No login cookie found # 未找到登录 cookie return redirect('login')
def protected_page_html(request): message = request.GET.get('message', 'This is a protected page.') message = request.GET.get('message', '这是一个受保护的页面。') return HttpResponse(f"<html><body><h1>Protected Content</h1><p>{message}</p></body></html>") return HttpResponse(f"<html><body><h1>受保护的内容</h1><p>{message}</p></body></html>")请记住,你需要为 login、dashboard、logout、home、protected_page 等添加 URL 模式,并创建 protected_page.html 模板,以便此示例能正常工作。
尽管直接操作 Cookie 有用,但它需要谨慎处理安全和状态。对于管理用户登录状态,Django 内置的 session 框架通常是首选且更安全的方法。
延伸阅读:
- Django Cookies 文档:https://docs.djangoproject.com/en/stable/ref/request-response/#setting-and-deleting-cookies
- MDN Web Docs 关于 HTTP Cookies:https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies