作为一名开发者,安全不应该是事后补救的“补丁”,而应当是代码逻辑的一部分。在现代 PHP 环境中,我们已经拥有了非常成熟的工具链来应对最常见的三大安全威胁。
SQL 注入:永远不要信任拼接的字符串
SQL 注入的根源在于将用户输入的数据当作 SQL 指令的一部分执行。
1. 核心防御:预处理语句(Prepared Statements)
在现代 PHP 中,无论使用原生的 PDO 还是流行的 ORM(如 Eloquent 或 Doctrine),都应强制使用参数化查询。
❌ 错误示范(危险):
$id = $_GET['id'];
// 攻击者可以输入 "1 OR 1=1"
$sql = "SELECT * FROM users WHERE id = " . $id;
$db->query($sql);
✅ 正确示范(PDO):
$id = $_GET['id'];
$stmt = $pdo->prepare('SELECT * FROM users WHERE id = :id');
// 数据与指令分离,数据库只会把 :id 当作纯字符串处理
$stmt->execute(['id' => $id]);
$user = $stmt->fetch();
2. 现代思维:类型安全
PHP 8 引入了更强的类型系统。在接收数据时进行强制类型转换,可以从源头上切断非法输入:
$userId = (int)($_GET['id'] ?? 0);
XSS(跨站脚本攻击):构建输出防火墙
XSS 的本质是非法脚本在用户的浏览器中被解析执行。防御的核心原则是:过滤输入,转义输出。
1. 转义输出(Escaping)
永远不要在不经过滤的情况下直接 echo 用户提交的内容。
✅ 原生 PHP 处理:
// 使用 htmlspecialchars 转换特殊字符
echo htmlspecialchars($userInput, ENT_QUOTES, 'UTF-8');
✅ 现代模板引擎(如 Twig/Blade):
现代引擎默认就是安全的。它们会自动进行转义:
{{ user_comment }} {# Twig 自动调用转义函数 #}
2. 内容安全策略(CSP)
通过 HTTP 响应头告诉浏览器,哪些外部资源是允许加载的。这是一种强大的辅助防御手段:
header("Content-Security-Policy: default-src 'self'; script-src 'self' https://trusted.cdn.com;");
CSRF(跨站请求伪造):身份的冒用
CSRF 诱导已登录用户在不知情的情况下,向服务器发送恶意请求(例如:利用受害者的 Cookie 修改密码)。
1. 核心防御:CSRF Token
为每个会话生成一个唯一的、不可预测的随机字符串。
实现逻辑:
- 在表单中埋入一个隐藏字段。
- 服务器端校验请求中的 Token 是否与 Session 中保存的一致。
✅ 代码示例:
// 1. 生成并存入 Session
if (empty($_SESSION['csrf_token'])) {
$_SESSION['csrf_token'] = bin2hex(random_bytes(32));
}
// 2. 在 HTML 表单中使用
<input type="hidden" name="csrf_token" value="<?= $_SESSION['csrf_token'] ?>">
// 3. 后端验证
if (!hash_equals($_SESSION['csrf_token'], $_POST['csrf_token'] ?? '')) {
die("CSRF 验证失败");
}
2. 现代方案:SameSite Cookie
在设置 Cookie 时,利用 SameSite 属性限制第三方请求携带 Cookie。
setcookie('session_id', $value, [
'expires' => time() + 3600,
'path' => '/',
'domain' => 'example.com',
'secure' => true,
'httponly' => true, // 防止 XSS 读取 Cookie
'samesite' => 'Lax' // 核心:有效抵御 CSRF
]);
总结:现代 PHP 安全清单
- SQL 注入:弃用
mysqli_query 拼接,全面拥抱 PDO 预处理。 - XSS:默认转义所有输出,使用成熟的模板引擎,并配合 CSP 策略。
- CSRF:关键操作必须校验 CSRF Token,并将 Cookie 设置为 HttpOnly & SameSite。
阅读原文:原文链接
该文章在 2026/4/24 10:47:24 编辑过