一、背景
最近在用trae写一个Django学生管理系统,需要验证测试登录功能。
二、脚本验证功能
- 自动获取CSRF Token
- 处理登录表单提交
- 保持登录状态访问其他接口
- 处理重定向
- 完整的错误处理
通过正则提取页面的CSRF Token
调用登录接口会重定方向
可以看到接口是会携带CSRF Token去登录的
三、编写思路
1. 为什么使用 Session?
- HTTP是无状态的 :每次请求都是独立的
- Session自动管理Cookie :登录成功后,Session会保存服务器返回的Cookie
- 后续请求自动携带Cookie :访问其他接口时不需要手动处理Cookie
2. CSRF Token 处理
Django的CSRF保护机制需要:
- 表单中的 csrfmiddlewaretoken :从页面HTML中提取
- Cookie中的 csrftoken :通过Session自动保存
- Referer头 :告诉服务器请求来源
3. 登录流程
1. 获取CSRF Token :访问登录页面,提取隐藏字段
2. 准备登录数据 :用户名、密码、用户类型、CSRF Token
3. 发送POST请求 :带上数据和Referer头
4. 判断登录成功 :通过重定向后的URL判断
4. 测试其他接口
登录成功后,Session中已有Cookie,直接访问其他需要登录的接口:
- 首页 ( / )
- 个人信息页 ( /profile/ )
- 成绩页 ( /grades/ )
四、验证脚本
import requests import re session = requests.session() def get_csrf_token(url): response = session.get(url) csrf_match = re.search(r'name=["\']csrfmiddlewaretoken["\'][^>]*value=["\']([^"\']+)["\']', response.text) if csrf_match: return csrf_match.group(1) return '' login_url = 'http://127.0.0.1:8000/login/' csrf_token = get_csrf_token(login_url) data = { 'username': 'admin88', 'password': 'Aa12345678', 'user_type': 'teacher', 'csrfmiddlewaretoken': csrf_token } headers = { 'Referer': 'http://127.0.0.1:8000/login/' } res = session.post(url=login_url, data=data, headers=headers, allow_redirects=True) # print(f"POST状态码: {res.status_code}") # print(f"重定向后URL: {res.url}") # 打印响应内容,查看错误信息 # print("\n响应内容:") # print(res.text) url = 'http://127.0.0.1:8000/student_list/' res = session.get(url=url) print(res.text)
五、遇到的问题及解决方案
问题1:403 Forbidden(CSRF验证失败)
原因 :
- 没有使用Session获取CSRF Token
- 没有添加Referer头
解决方案 :
- 使用 session.get() 获取Token(保存Cookie)
- 添加 Referer 头指向登录页面
Django 的 CSRF 保护需要验证 三个东西 :
| 验证项 | 来源 | 说明 |
| csrfmiddlewaretoken | 表单隐藏字段 | 我们从HTML中提取的 |
| csrftoken | Cookie | Session自动带的 |
| Referer | HTTP请求头 | 浏览器自动带的 |
三个必须同时匹配 ,才能通过验证。
Referer 的作用
Referer 是 HTTP 请求头的一部分,告诉服务器"这个请求是从哪个页面发起的"。
浏览器发送POST请求时,会自动带上Referer头: Referer: http://127.0.0.1:8000/login/为什么 Django 要检查 Referer?
这是为了防止 跨站请求伪造(CSRF)攻击 :
攻击场景
假设你已登录银行网站 bank.com ,并且银行网站没有 CSRF 保护:
1. 你访问了一个恶意网站 hacker.com
2. 恶意网站用你的身份发送请求到 bank.com/transfer?to=hacker&money=10000
3. 因为浏览器自动带上 Cookie,银行服务器以为是你本人操作
Django 的防护
Django 要求:
- 请求必须来自 同一个域名 (通过 Referer 判断)
- 请求必须携带 正确的 Token
这样,即使恶意网站能诱导浏览器发送请求:
- 没有正确的 csrfmiddlewaretoken ,会被拒绝
- Referer 不是 bank.com ,会被拒绝
问题2:重定向后返回登录页
原因 :
- 用户名或密码错误
- 用户类型不匹配
解决方案 :
- 确认用户存在且密码正确
- 确保用户类型与注册时一致
问题3:Token过期
原因 :
- 多次获取Token但只使用一次
- 每次GET请求都会生成新Token
解决方案 :
- 每次登录前只GET一次Token
- 使用同一个Session完成整个流程