以下是第三周周四学习内容的详细展开,聚焦 Web 应用完整数据流转链路。今天你要亲手搭建一个简易登录处理脚本,用浏览器和抓包工具观察从输入框到服务器响应全过程,并画出数据流向图。这是理解 SQL 注入、XSS、逻辑漏洞的绝对前提。

第三周·周四:数据流转全链路——前端→HTTP请求→后端处理→数据库存储→响应返回
🎯 今日学习目标(达成效果)
- 能在不参考资料的情况下画出一次登录请求的完整数据流向图,包含:浏览器表单 → HTTP 请求 → Web 服务器 → 后端脚本 → 数据库查询 → 响应返回;
- 能正确说出各环节的职责、数据格式及潜在安全风险(如明文传输、注入点、错误信息泄露);
- 能独立搭建一个包含前端表单、后端接收(PHP 或 Python)、数据库查询的简易登录模拟环境;
- 能**使用浏览器开发者工具(Network 面板)**找到登录请求,查看请求方法、载荷(Payload)和响应状态;
- 能从安全角度指出每个环节可能出现的漏洞类型(注入、敏感信息泄露、逻辑绕过等),为后续漏洞学习建立全景视图。
📘 一、一次登录请求的完整旅程
假设你正在访问一个网站,在登录页面输入账号 admin、密码 pass123,点击“登录”按钮。下面是数据依次经过的环节:
浏览器 (前端)
- 用户在 <input> 中填入数据,点击提交按钮或按回车。
- 浏览器根据 <form> 的 action 和 method 构建 HTTP 请求。
- 若 method="POST",数据被编码放入请求体;若 GET,则拼接在 URL 后面。
- 安全点:此时数据仍为明文(除非页面已 HTTPS),且完全受用户控制,任何前端验证都只是“温馨提示”。
HTTP 请求报文
- 浏览器构造类似以下的请求报文并发送到服务器:POST /login.php HTTP/1.1
Host: www.example.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 29username=admin&password=pass123
- 安全点:缺乏 HTTPS 时,中间人可直接嗅探密码;即使使用 POST,密码在 HTTP 下仍为明文。
Web 服务器(如 Apache/Nginx)
- 收到请求后,根据 URL 路径将请求分发给对应的后端处理程序(如 PHP 解释器、Python WSGI 应用)。
- 服务器可能在此进行基础过滤(URL 长度、请求方法限制等),但不做业务逻辑校验。
后端脚本(应用逻辑层)
- 后端代码(PHP、Python、Java 等)获取参数:$_POST['username']、$_POST['password']。
- 执行业务逻辑:如检查用户名是否存在、密码是否正确、账号是否锁定等。
- 关键安全动作:必须对输入进行过滤/转义、使用参数化查询、验证密码哈希。
- 示例 PHP 代码片段:$user = $_POST['username'];
$pass = $_POST['password'];
// 危险写法:直接拼接 SQL(导致注入)
$sql = "SELECT * FROM users WHERE username='$user' AND password='$pass'";
// 安全写法:使用预处理语句
$stmt = $pdo->prepare("SELECT * FROM users WHERE username=?");
$stmt->execute([$user]); - 安全点:此处是 SQL 注入、命令注入、业务逻辑漏洞的核心发源地。
数据库系统(如 MySQL)
- 接收 SQL 查询,在表里查找匹配的记录。
- 将结果集返回给后端脚本(成功找到用户 → 登录有效;未找到 → 返回错误)。
- 安全点:若使用 root 账户且无权限隔离,一次注入可泄露全库。
响应返回
- 后端根据业务结果生成 HTTP 响应:
- 成功可能返回 HTTP/1.1 302 Found 重定向到用户主页,并设置会话 Cookie。
- 失败返回 200 OK 并显示错误信息“用户名或密码错误”。
- 响应报文包含状态码、头部(Set-Cookie)、HTML 内容。
- 安全点:错误信息过于详细可能被用于枚举用户名(如区分“用户不存在”与“密码错误”),Cookie 属性缺失(无 HttpOnly/Secure)则易被窃取。
全链路总结:前端只是数据的起点,真正的安全防线必须在服务器端每一层都布防。
✍️ 二、动手实践:搭建简易登录模拟环境
为了让你亲眼看到数据流转,我们搭建一个最小化的环境:HTML 表单 + Python 后端 + SQLite 数据库(无需复杂安装)。你也可以使用 PHP + MySQL,但 Python 更易快速实验。
实验准备
确认系统已安装 Python3,无需额外安装数据库,SQLite 内置在 Python 中。
步骤 1:创建目录和前端页面
mkdir ~/login_lab
cd ~/login_lab
创建 index.html(前端表单):
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>登录实验</title>
</head>
<body>
<h1>用户登录</h1>
<form action="/login" method="post">
<label>用户名:<input type="text" name="username"></label><br>
<label>密码:<input type="password" name="password"></label><br>
<input type="submit" value="登录">
</form>
</body>
</html>
步骤 2:创建后端脚本(Python 简易 HTTP 服务器处理登录)
我们不使用框架,直接写一个可处理 POST 的脚本 server.py:
import http.server
import sqlite3
import urllib.parse
import os
# 初始化数据库:创建一个 users 表并插入测试账号
def init_db():
conn = sqlite3.connect('users.db')
c = conn.cursor()
c.execute("CREATE TABLE IF NOT EXISTS users (id INTEGER PRIMARY KEY, username TEXT, password TEXT)")
c.execute("INSERT OR IGNORE INTO users (id, username, password) VALUES (1, 'admin', 'pass123')")
conn.commit()
conn.close()
init_db()
class LoginHandler(http.server.BaseHTTPRequestHandler):
def do_GET(self):
if self.path == '/' or self.path == '/index.html':
try:
with open('index.html', 'rb') as f:
content = f.read()
self.send_response(200)
self.send_header('Content-type', 'text/html; charset=utf-8')
self.end_headers()
self.wfile.write(content)
except:
self.send_error(404)
else:
self.send_error(404)
def do_POST(self):
if self.path == '/login':
# 获取请求体长度
content_length = int(self.headers['Content-Length'])
post_data = self.rfile.read(content_length).decode('utf-8')
# 解析表单数据
params = urllib.parse.parse_qs(post_data)
username = params.get('username', [''])[0]
password = params.get('password', [''])[0]
# 查询数据库(此处为了简单使用拼接,实际应用需参数化)
conn = sqlite3.connect('users.db')
c = conn.cursor()
# ⚠️ 注意:此处仅为演示,后面安全课程会用参数化替代
query = f"SELECT * FROM users WHERE username='{username}' AND password='{password}'"
c.execute(query)
result = c.fetchone()
conn.close()
if result:
self.send_response(200)
self.send_header('Content-type', 'text/html; charset=utf-8')
self.end_headers()
self.wfile.write(b"<h1>Login Success! Welcome " + result[1].encode() + b"</h1>")
else:
self.send_response(200)
self.send_header('Content-type', 'text/html; charset=utf-8')
self.end_headers()
self.wfile.write(b"<h1>Login Failed! Invalid credentials.</h1>")
else:
self.send_error(404)
if __name__ == '__main__':
server_address = ('', 8080)
httpd = http.server.HTTPServer(server_address, LoginHandler)
print("Server running on http://127.0.0.1:8080")
httpd.serve_forever()
步骤 3:启动服务并测试
python3 server.py
在浏览器访问 http://127.0.0.1:8080,会看到登录表单。输入 admin / pass123 点击登录,应显示 “Login Success! Welcome admin”。输入错误密码则显示失败信息。
步骤 4:使用开发者工具观察完整数据流
按 F12 → Network 面板,勾选 “Preserve log”。
点击登录后,找到名为 login 的请求:
- Headers → Request Method: POST
- Request Headers:查看 Content-Type
- Payload(或 Request Payload):看到 username=admin&password=pass123
- Response:查看返回的 HTML 内容及状态码。
安全观察:
- 即使使用 POST,密码在载荷中仍然是明文(password=pass123),如果不使用 HTTPS,传输过程可被嗅探。
- 后端代码中我们使用了拼接 SQL(f"SELECT * FROM users WHERE username='{username}' AND password='{password}'"),这是典型的 SQL 注入风险。尝试在用户名框输入 admin'–(单引号+注释符),密码随便填,观察是否会绕过登录?(此环境会,因为注释掉了密码检查)
思考:今天的环境是故意不安全的,正是为了直观展示注入点。后续学习 SQL 注入时,你会明白原理并深入利用。
📝 三、画出你的数据流向图(今日必做作业)
请在一张纸上或电子笔记中画出从输入账号到登录成功全过程的流向图,标注每个环节的安全点。参考结构如下:
[浏览器表单] → [HTTP POST 明文载荷] → [Nginx/Apache 接收] → [PHP/Python 脚本]
↑ ↓
[用户输入] [数据库查询 (可能注入)]
↑ ↓
[显示结果] ← [HTTP 响应 + Set-Cookie] ← [返回结果给服务器] ← [数据库返回数据]
必须标注出:明文传输风险、SQL 注入点、错误信息泄露风险、Cookie 属性设置。
📝 四、课后测试题与解析
测试题 1:用户输入账号密码点击登录后,数据依次经过哪些环节?请用文字或图描述。
参考答案:
测试题 2:在 F12 网络面板中找到登录请求的载荷。请写出操作步骤。
参考答案:
安全延伸:在真实渗透测试中,你还会使用 BurpSuite 或 Wireshark 抓取同样信息,并在不依赖浏览器的情况下篡改这些载荷。
✅ 今日学习效果自检清单
- 我能闭眼画出登录请求的完整数据流向图(前端→网络→后端→数据库→返回)
- 我搭建了 Python 登录模拟环境,并成功登录和失败
- 我在 Network 面板中找到了 POST 请求,并查看了载荷(用户名和密码)
- 我意识到了明文传输、SQL 拼接的风险,并尝试了 admin'– 绕过(可在测试题环境尝试)
- 我理解了每个环节都可能存在安全漏洞,这为后续专项漏洞学习提供了“地图”
⚠️ 阶段避坑重点
- 不要在自己的模拟环境中使用真实密码:我们使用简单密码和测试数据库,仅用于学习。
- 不要对外暴露实验服务:默认监听在 127.0.0.1,如果改成 0.0.0.0 且没有防火墙,可能被外部访问。
- 不要将今天的有意漏洞代码用于生产:SQL 拼接是典型的错误示范,下周我们学习 SQL 注入后,会教参数化查询的正确写法。
- 不要只背流程而不动手画图:画图能固化逻辑,画错立刻知道哪里理解有偏差。强烈建议用笔在纸上画一遍。
明天(周五)我们将学习 开发工具 Network 面板实战,继续深化对 HTTP 请求响应的分析能力,为接下来的 SQL 注入、XSS 等漏洞学习培养精准的观察力。请保留今天的实验环境,明天会直接用它来练习分析 Headers 和 Response。






