Django Session 登录验证完整指南:配置、视图与中间件校验

晚来风
晚来风
发布时间:2026-10-12| 3人浏览过
原创

Django 默认提供完整的 Session 管理机制,通过中间件自动维护用户会话状态。本文详细演示如何利用自定义 User 模型配合 request.session 完成注册、登录、登出全流程,并提供基于装饰器与全局中间件的统一权限校验方案,帮助开发者快速搭建安全的后台登录验证体系。

Session 运行机制与基础配置

Django 的 Session 功能依赖 'django.contrib.sessions.middleware.SessionMiddleware' 中间件。默认情况下,会话数据存储在数据库的 django_session 表中。其标准工作流如下:

  1. 第1步:登录写入状态。目的:建立用户凭证。入口:登录接口 LoginView.post。动作:验证账号密码成功后,执行 request.session["username"] = username。完成状态:浏览器返回 sessionid=xxx Cookie,数据库新增对应 session_key 记录。
  2. 第2步:统一校验访问权限。目的:确保接口安全。入口:受保护路由。动作:中间件或视图读取 Cookie 中的 Key,在数据库中解码匹配 session_data。完成状态:匹配成功放行,否则返回 401 未登录提示。
  3. 第3步:注销清除会话。目的:终止登录态。入口:登出接口。动作:执行 del request.session[...] 或 request.session.flush()。完成状态:session_data 被清空或数据库记录物理删除,后续请求视为未登录。

相关参数可在 settings.py 中调整:

  • SESSION_COOKIE_AGE:默认 1209600 秒(14天),控制 Cookie 有效期。
  • SESSION_COOKIE_NAME:Cookie 中的 Key 名称,默认 sessionid。
  • SESSION_ENGINE:数据存储引擎,默认 'django.contrib.sessions.backends.db' 表示使用数据库存储,也可改为文件或缓存。

核心操作方法

在视图函数中,request.session 的行为类似字典,支持以下关键操作:

  • 字典式读写:直接赋值写入 request.session["username"] = username;通过 request.session.get("username") 读取;使用 del request.session["username"] 移除特定键值对。注意:del 仅清空该条记录的 session_data 字段内容,不会删除数据库行。
  • 彻底销毁:调用 request.session.flush() 会直接在数据库中物理删除该会话记录,适用于需要强制退出的场景。
  • 查询与清理:request.session.keys() 与 items() 用于调试查看已存内容;request.session.get_expiry_age() 获取剩余有效秒数;Session.objects.clear_expired() 可批量清理过期表记录。

注册、登录与注销接口实现

以下为基于自定义 User 模型的完整视图代码。接口接收 JSON Body,通过 make_password 加密存储密码,并利用 request.session 管理登录状态。

# users/urls.py
from django.urls import path
from users.views import LoginView, RegisterView, LogoutView, UserInfoView
urlpatterns = [
    path("register", RegisterView.as_view()),
    path("login", LoginView.as_view()),
    path("logout", LogoutView.as_view()),
    path("user/info", UserInfoView.as_view()),
]
# users/views.py
from django.contrib.auth.hashers import make_password, check_password
from django.http import JsonResponse
from django.views import View
from users.models import User
import json

# 用户注册
class RegisterView(View):
    def post(self, request):
        data = json.loads(request.body)
        username, password = data.get("username"), data.get("password")
        if not username or not password:
            return JsonResponse({"code": -1, "msg": "参数缺失"}, status=400)
        if User.objects.filter(username=username).exists():
            return JsonResponse({"code": -1, "msg": "用户名已存在"})
        User.objects.create(username=username, password=make_password(password))
        return JsonResponse({"code": 0, "msg": "注册成功"})

# 用户登录
class LoginView(View):
    def post(self, request):
        data = json.loads(request.body)
        username, password = data.get("username"), data.get("password")
        if not username or not password:
            return JsonResponse({"code": -1, "msg": "参数缺失"}, status=400)
        user = User.objects.filter(username=username).first()
        if not user:
            return JsonResponse({"code": -1, "msg": "用户不存在"})
        if check_password(password, user.password):
            request.session["username"] = username
            return JsonResponse({"code": 0, "msg": "登录成功"})
        return JsonResponse({"code": -1, "msg": "密码错误"})

# 用户信息(需登录)
class UserInfoView(View):
    def post(self, request):
        username = request.session.get("username")
        if username:
            return JsonResponse({"code": 0, "msg": f"当前登录用户:{username}"})
        return JsonResponse({"code": -1, "msg": "未登录"}, status=401)

# 用户登出
class LogoutView(View):
    def post(self, request):
        del request.session["username"]
        return JsonResponse({"code": 0, "msg": "登出成功"})

统一权限校验的两种方案

若系统中大量接口均需前置登录判断,逐层添加逻辑会导致代码冗余。推荐以下两种自动化校验方案:

方案一:函数装饰器

封装通用装饰器,侵入性低,适合局部接口保护:

def login_required_manual(func):
    def wrapper(*args, **kwargs):
        request = args[1]
        if not request.session.get("username"):
            return JsonResponse({"code": -1, "msg": "未登录"}, status=401)
        return func(*args, **kwargs)
    return wrapper

# 使用示例
class RestrictedDataView(View):
    @login_required_manual
    def get(self, request):
        return JsonResponse({"data": "敏感信息"})

方案二:全局中间件(推荐)

将鉴权逻辑提取至中间件,所有请求在进入视图前统一拦截,便于集中管理白名单:

# hunter/middlewares/auth_middleware.py
from django.http import JsonResponse

class AuthMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
        whitelist = ["/users/register", "/users/login"]
        if request.path not in whitelist:
            if not request.session.get("username"):
                return JsonResponse({"code": -1, "msg": "请先登录"}, status=401)
        return self.get_response(request)

配置生效需在 settings.py 中添加至 MIDDLEWARE 列表(注意位置通常在 SessionMiddleware 之后):

MIDDLEWARE = [
    ...
    'hunter.middlewares.auth_middleware.AuthMiddleware',
    ...
]

直接读取 Session 数据库表

调试时可直接操作 django.contrib.sessions.models.Session 查看底层数据。通过 session_key 获取记录后,使用 get_decoded() 即可还原存入的原始字典:

from django.contrib.sessions.models import Session

session_obj = Session.objects.get(session_key="你的session_key值")
data_dict = session_obj.get_decoded()
print(data_dict)  # 输出如 {'username': 'root'}

总结

本文系统梳理了 Django Session 从环境配置、状态管理到权限拦截的完整工作链路。通过自定义视图控制会话生命周期,并结合装饰器或中间件实现统一鉴权,能够显著提升项目的安全性与代码可维护性。以上就是 Django Session 登录验证操作的详细内容,更多关于 Django 进阶开发与会话管理的资料请关注本站其它相关文章!

相关标签:

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。