1.从用户点击登录到后端验证成功-具体环节2.用户输入 工号密码用户在登录表单中输入工号和密码点击“登录”按钮。const username document.getElementById(loginUser).value.trim(); const password document.getElementById(loginPass).value.trim();3.CSRF Token 防伪印章先解释什么是浏览器服务器HTTP各个负责的板块是什么浏览器客户端类似于顾客去餐厅点餐服务器服务端类似厨房接单做菜出菜HTTP类似于规定怎么点菜怎么回菜就是规定主站和从站的通讯的方式和内容是什么总结就是两者的之间的通讯协议怎么通讯比较稳定然后解释什么是Cookie 有个最底层的事实就是HTTP协议是无状态的无法区分两个客户端还是一个客户端对一个服务器进行一个相同的请求需求还是进行两个不同的请求需求服务器不知道请求的客户端是谁意味着每一次HTTP请求之间是完全独立的服务器无法知道“这次请求的用户“是不是“刚才那个用户”。最简单的解决方案是服务器无法识别客户端那就让客户端自己带一个“身份证”过来每次请求时客户端主动出示这个证件服务器一看就知道是谁所以就是cookie诞生的缘故Cookie 的具体实现机制服务器创建当服务器第一次收到请求时它决定给这个客户端发一个唯一标识比如一串随机数字放在 HTTP 响应的Set-Cookie头部里。浏览器存储浏览器收到响应后按照规则域名、路径、有效期等把这个键值对保存在本地。浏览器自动发送之后只要浏览器向同一个域名发起新的请求就会自动在请求头中加入Cookie: 标识值。服务器识别服务器从请求头中取出 Cookie查一下数据库就知道这是哪个用户的会话了。总结所以Cookie 的本质就是“在无状态的 HTTP 之上由浏览器帮助实现的一个客户端状态存储与自动回传机制”。它不是为了复杂而存在而是为了解决最原始的问题——如何让服务器记住你。最后解释什么是CAEF Token防伪印章 第一因为HTTP 是无状态的服务器每收到一个请求都和上一个请求没有任何关系。为了让服务器认出“你是刚才那个已经登录的人”浏览器和服务器达成了这样一个约定你登录成功后服务器在响应头里放一个Set-Cookie: sessionidabc123。浏览器收到后把这个sessionidabc123存起来。关键来了以后只要你对同一个域发起请求浏览器都会自动、无条件地把这个sessionidabc123放在请求头里发给服务器。服务器看到sessionidabc123就知道“这是刚才那个登录用户”。这个机制本身是完美的它解决了 HTTP 无状态的问题。第二这个机制有个缺点就是:浏览器只知道一条规则请求的目标域名匹配就带上这个域名的cookie浏览器完全不管这个请求是谁发起的。你点击一个链接、提交一个表单、或者页面里一张隐藏图片的src指向了目标服务器只要目标域名相同浏览器都会“尽职尽责”地把 Cookie 带上。这就是问题的根源浏览器无法区分“这个请求是用户自己的意图”还是“别的网站诱导发出的请求”。简单的来说假如一个欺骗性的链接直接指向公司的财务网站浏览器也会自动、无条件地把这个sessionidabc123放在请求头里发给服务器对财务系统的相关数据进行操作因为从服务器视角看这就是一个完全合法的请求——它带着正确 Session ID来自正确的用户。第三CSRF的定义CSRF 恶意网站利用浏览器“自动携带 Cookie”的天性假借你的身份向目标网站发起恶意请求。第四怎么解决既然浏览器无法区分请求来源那我们就给它一个“只有真正的页面才能拿到的凭证”。这个凭证就是CSRF Token 防伪印章真正的factory.com页面里嵌入了一个随机生成的 Token通过{% csrf_token %}或者 Cookie 中的csrftoken。浏览器把这个 Token 放在请求头X-CSRFToken中连同 Cookie 一起发送。服务器收到后先校验 Token它是不是我之前发给这个用户的如果没有、或者不匹配直接拒绝请求。恶意网站 永远拿不到这个 Token因为浏览器的同源策略阻止了跨域读取factory.com页面里的内容或 Cookie。所以它发起的请求没有 Token服务器直接拒绝。形象类比场景类比你进入一个高档会所浏览器访问factory.com前台看了你的会员卡给你发了一张门禁卡Session ID登录成功服务器下发sessionidCookie以后你每次进出只需在刷卡器上刷一下门禁卡就行不用再查会员卡浏览器每次请求自动携带 Cookie有一天一个坏人趁你路过时把一张“转账申请单”塞到你手里诱导你扔进会所的“业务箱”里恶意网站诱导你发出一个恶意请求业务员看到申请单是随着你的门禁卡一起投进来的就默认是你本人提交的执行了转账服务器看到有效 Cookie认为是合法请求执行操作CSRF Token 就像是一张必须用特制印章盖在申请单上才能生效的防伪标记。坏人虽然可以塞给你申请单但他的申请单上没有你独有的印章所以业务员一看就知道是假的恶意网站拿不到 CSRF Token请求被后端拒绝总结Cookie 和 CSRF 的关系Cookie 是为“无状态 HTTP 提供状态”的机制CSRF 是这种机制的一个天然缺陷被恶意利用的结果。后端程序# 2. ensure_csrf_cookie 装饰器 # 【对应原理CSRF Token 的“防伪印章”下发】 # 作用无论用户是 GET 还是 POST 访问这个视图 # Django 都会在响应头里加上 Set-Cookie: csrftoken随机字符串 # 浏览器拿到后存起来以后前端 JS 可以读取它放到请求头里作为凭证 ensure_csrf_cookie前端程序:// 步骤2读取 CSRF Token function getCSRFToken() { return document.cookie.split(; ) .find(row row.startsWith(csrftoken)) ?.split()[1]; } headers: { X-CSRFToken: getCSRFToken() }展现完整的代码# 1. 导入必要的工具 import json # 用于解析 JSON 格式的请求体 from django.contrib.auth import authenticate, login # authenticate验证用户名密码 # login验证通过后把用户信息写入 session from django.http import JsonResponse # 返回 JSON 格式的响应给前端 from django.views.decorators.csrf import ensure_csrf_cookie # 确保浏览器能拿到 CSRF Token from django.views.decorators.http import require_POST # 限制这个视图只接受 POST 请求 # 2. ensure_csrf_cookie 装饰器 # 【对应原理CSRF Token 的“防伪印章”下发】 # 作用无论用户是 GET 还是 POST 访问这个视图 # Django 都会在响应头里加上 Set-Cookie: csrftoken随机字符串 # 浏览器拿到后存起来以后前端 JS 可以读取它放到请求头里作为凭证 ensure_csrf_cookie # 3. require_POST 装饰器 # 【对应原理POST 请求——数据放在请求体不暴露在 URL】 # 作用如果有人用 GET 方式访问这个接口Django 直接返回 405 错误 # 因为登录是“提交密码并创建会话”必须用 POST require_POST def api_login(request): 登录 API 视图 处理前端发来的登录请求验证用户身份返回 JSON 结果 # 4. 解析 JSON 请求体 # 【对应原理JSON 解析——网络只能传文本需要“解码”】 # request.body 是前端发来的原始字节流内容是 JSON 字符串 # 比如b{username:admin,password:admin123456} # json.loads() 把这个字符串转成 Python 字典才能取出 username 和 password try: data json.loads(request.body) # ← 解码 JSON 字符串 → Python 字典 username data.get(username, ) # ← 取出用户名 password data.get(password, ) # ← 取出密码 except json.JSONDecodeError: # 如果 JSON 格式错误比如少了括号返回 400 错误 return JsonResponse({success: False, message: 数据格式错误}, status400) # 5. 验证用户身份 # 【对应原理Cookie / Session 机制——服务器“记住”用户】 # authenticate() 会根据 settings.AUTHENTICATION_BACKENDS 里配置的认证后端 # 逐一检查用户名和密码是否匹配数据库中的用户记录。 # 如果匹配返回用户对象如果不匹配返回 None user authenticate(request, usernameusername, passwordpassword) if user is not None: # 6. 登录成功创建会话 # 【对应原理Cookie 的诞生——服务器让客户端带“身份证”】 # login() 做了两件事 # (1) 在服务器端的 session 表里记录这个用户的会话 # (2) 在响应头里加上 Set-Cookie: sessionidabc123HttpOnlyJS 无法读取 # 以后浏览器每次请求这个域名都会自动带上 sessionid # 服务器看到它就知道“这是刚才登录的那个用户” login(request, user) # 7. 获取用户角色信息准备返回给前端 # getattr(user, role, other) 是安全取值 # 如果 user 对象有 role 属性就取它没有就默认返回 other role getattr(user, role, other) # 拼接显示名称优先用工号姓名如果没有工号就用用户名 display_name ( f{user.employee_id} {user.get_full_name()} if user.employee_id else user.get_username() ) # 8. 返回成功响应 # 【对应原理API 接口——前后端约定的 JSON 通信格式】 # 前端收到这个 JSON 后会根据 success 字段判断登录是否成功 # 并根据 role 字段显示不同的界面权限 return JsonResponse({ success: True, message: 登录成功, display_name: display_name, role: role, is_staff: user.is_staff, }) else: # 9. 验证失败 # 返回 401 Unauthorized前端收到后显示“工号或密码错误” return JsonResponse({success: False, message: 工号或密码错误}, status401)完整流程串联原理 → 代码对应表步骤原理代码体现① 用户访问登录页浏览器向服务器发起请求http://127.0.0.1:8000/accounts/login/② 服务器下发 CSRF Token防伪印章确保后续请求来自真实页面后端视图上的ensure_csrf_cookie③ 浏览器保存 TokenCookie 存储机制浏览器收到Set-Cookie: csrftokenxxx④ 用户输入账号密码身份认证的起点input idloginUser,input idloginPass⑤ 前端发起 POST 请求数据放在请求体不暴露 URLfetch(..., { method: POST, body: ... })⑥ 前端携带 CSRF Token防伪印章随请求发送headers: { X-CSRFToken: getCSRFToken() }⑦ JSON 编码网络只能传文本JSON.stringify({ username, password })⑧ URL 路由找到处理请求的函数path(api/login/, api_login)⑨ JSON 解码把文本还原为数据json.loads(request.body)⑩ 验证用户检查用户名密码authenticate(username..., password...)⑪ 创建 Session让服务器“记住”用户login(request, user)⑫ 下发 sessionid Cookie身份证后续请求自动携带Set-Cookie: sessionidabc123Django 自动⑬ 返回 JSON 结果前后端约定的通信格式JsonResponse({success: True, ...})这些就是你的工厂系统登录流程中Cookie、CSRF Token、POST 请求、JSON 解析、路由、API六个核心概念在代码中的具体对应位置。每一行都对应着之前讨论的第一性原理。