7.1 认证系统与会话管理


文档摘要

7.1 认证系统与会话管理 本节摘要:Django 自带一套完整认证体系:用户模型、密码哈希、登录登出视图、会话管理。本节用内置组件搭出墨迹博客的登录系统,讲清 authenticate 与 login 的分工、会话 Cookie 的配合机制、以及扩展用户信息的 Profile 模式。绝大多数项目不该自己发明登录。 内置用户模型:先认识再扩展 django.contrib.auth 提供现成的用户模型,字段覆盖用户名、密码哈希、邮箱、两个布尔开关(是否员工、是否活跃)。它最值得信任的部分是密码管理: 数据库里存的是 PBKDF2 派生哈希加随机盐,算法参数记录在哈希串前缀里,将来升级算法,老用户下次登录时自动重哈希——这套机制是第 1 章"框架替你挡的箭"里最厚的一支。

7.1 认证系统与会话管理

本节摘要:Django 自带一套完整认证体系:用户模型、密码哈希、登录登出视图、会话管理。本节用内置组件搭出墨迹博客的登录系统,讲清 authenticate 与 login 的分工、会话 Cookie 的配合机制、以及扩展用户信息的 Profile 模式。绝大多数项目不该自己发明登录。

内置用户模型:先认识再扩展

django.contrib.auth 提供现成的用户模型,字段覆盖用户名、密码哈希、邮箱、两个布尔开关(是否员工、是否活跃)。它最值得信任的部分是密码管理:

from django.contrib.auth.models import User user = User.objects.create_user("xiaomo", "x@moji.dev", "强密码123") # create_user 负责哈希;绝不要用 create 直接塞明文密码 user.set_password("新密码") # 改密码同样走哈希 user.check_password("新密码") # 校验而不接触哈希细节 → True

数据库里存的是 PBKDF2 派生哈希加随机盐,算法参数记录在哈希串前缀里,将来升级算法,老用户下次登录时自动重哈希——这套机制是第 1 章"框架替你挡的箭"里最厚的一支。

一个老问题:内置字段不够怎么办?两条路。简单场景用 Profile 模式外挂(本节末尾);确实要改核心字段(比如用邮箱登录)则在一开始就替换自定义用户模型。替换必须发生在第一次迁移之前,事后改造要迁移用户数据,代价极高——这是 Django 项目十大后悔榜的常客。

登录登出:三个组件拼装

内置认证视图开箱即用,路由一行接入:

# 根路由 path("accounts/", include("django.contrib.auth.urls")),

自动获得登录、登出、密码修改、密码重置等一整套路由。要做的只是提供登录页模板(约定位置):

{# registration/login.html #} {% extends "base.html" %} {% block content %} <form method="post"> {% csrf_token %} {{ form.as_p }} <button type="submit">登录</button> </form> {% endblock %}

墨迹博客的作者登录后的跳转:

# settings 配置 LOGIN_REDIRECT_URL = "blog:article-list" # 登录成功去哪 LOGOUT_REDIRECT_URL = "blog:article-list" # 登出后去哪 LOGIN_URL = "login" # 未登录被拦时去哪

登出甚至不需要模板——LogoutView 收到请求即清除会话并跳转。若想自己写登录逻辑(比如加图形验证码),核心 API 是两步,分工必须分清:

from django.contrib.auth import authenticate, login def my_login(request): user = authenticate(request, username="...", password="...") # authenticate:只验证凭证,返回用户对象或 None,不带任何状态 if user is not None: login(request, user) # login:把用户写进会话,产生会话状态 return redirect("blog:article-list") ...

authenticate 认人,login 记人。只调前者页面毫无变化,只调后者会报错——这对 API 名字的辨析是面试与实战的双料高频题。

会话:HTTP 记忆的载体

HTTP 请求彼此无记忆,会话机制补上这块短板。流程闭环如下:

  1. 首次访问,框架生成随机会话标识;
  2. 响应通过 Set-Cookie 头把标识种进浏览器;
  3. 后续请求浏览器自动带上这个 Cookie;
  4. SessionMiddleware 凭标识从会话存储取出该用户的会话数据,挂到 request.session;
  5. login 函数把用户主键写进会话;此后 AuthenticationMiddleware 把 request.user 恢复成真实用户对象。

认证与会话时序

认证与会话时序

会话默认存数据库(django_session 表),可切缓存或 Redis 后端提速。浏览一遍会话的操作接口:request.session 取值、set_expiry 设过期、flush 登出时清空。直接操作用户的 API 还有一对判断:is_authenticated 区分登录与否。注意它是属性不是方法,模板里 {{ user.is_authenticated }} 直接用。

Profile:扩展用户信息的正道

用户的昵称、头像、签名不属于核心认证,外挂一个一对一模型最干净:

class Profile(models.Model): user = models.OneToOneField( User, on_delete=models.CASCADE, related_name="profile") nickname = models.CharField("昵称", max_length=50, blank=True) bio = models.TextField("签名", blank=True)

用信号(第 11 章展开)在建用户时自动建 Profile,之后模板里 {{ user.profile.nickname }} 一路点到底。一对一字段的妙处:反查唯一,user.profile 不存在时抛异常而不是返回列表,语义与"一人一份资料"严丝合缝。

💡 判断信息该进核心还是 Profile 的一条线:认证流程要用的进核心,展示用的进 Profile。拿不准的都放 Profile,将来合并易、拆分难的方向要选对。

会话安全的两面

会话机制建立起来后,它的安全面也要同步正视:会话 Cookie 就是用户的临时身份证,谁拿到它谁就是那个人。第一个要点是登出的彻底性——退出登录不仅要删服务端的会话记录,还要让浏览器端的 Cookie 失效,只做一半会导致看起来退出了、旧凭证仍可用的假安全。第二个要点是敏感操作的凭证刷新——修改密码、绑定邮箱这类操作之后,应当刷新会话标识,防止会话固定攻击:攻击者预设的会话标识在用户登录后必须作废重发。第三个要点是记住登录的取舍——延长会话寿命提升便利,也延长了凭证暴露的窗口,内容型站点给七天,涉及支付的场景给两小时,寿命应与数据敏感度挂钩。这些细节平时无声无息,出事时都是头版新闻。认证体系的安全审计,本质上就是围着这张临时身份证检查每一个流通环节。

本节要点回顾

  • create_user 与 set_password 管哈希,明文密码永远不进数据库。
  • authenticate 认人、login 记人,两步分工不可混。
  • 会话闭环五步:种 Cookie、带 Cookie、取会话、写主键、恢复 user。
  • 扩展用户走 Profile 外挂,替换核心用户模型必须赶在第一次迁移前。

认识了"你是谁",下一节约束"你能做什么":权限与分组。


作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U