模式切换
PHP 安全性
防止 SQL 注入
使用预处理语句:
预处理语句通过占位符(?
或命名参数)避免直接拼接用户输入,防止 SQL 注入。
php
// 使用 PDO 进行安全的数据库查询
$stmt = $pdo->prepare("SELECT * FROM users WHERE email = :email");
$stmt->execute(['email' => $userEmail]);
$result = $stmt->fetch();
使用 mysqli
的预处理语句:
php
$stmt = $mysqli->prepare("SELECT * FROM users WHERE email = ?");
$stmt->bind_param("s", $userEmail);
$stmt->execute();
$result = $stmt->get_result();
避免拼接 SQL 语句:
不要在 SQL 语句中直接拼接用户输入,所有用户输入的数据都应该进行适当的过滤和转义。
防止 XSS(跨站脚本攻击)
输出转义:
在输出用户输入内容时,使用 htmlspecialchars()
转义特殊字符。
php
$safeOutput = htmlspecialchars($userInput, ENT_QUOTES, 'UTF-8');
echo $safeOutput;
设置内容安全策略(CSP):
使用 HTTP 响应头设置 CSP 来限制可执行的脚本来源。
php
header("Content-Security-Policy: default-src 'self'");
避免直接输出用户输入的数据:
对用户提交的数据进行清理或过滤,避免存储恶意脚本。
CSRF(跨站请求伪造)防护
使用 CSRF 令牌:
在表单中生成唯一的 CSRF 令牌,并在服务器端验证。
php
// 生成 CSRF 令牌
session_start();
$_SESSION['csrf_token'] = bin2hex(random_bytes(32));
html
<!-- 在表单中包含 CSRF 令牌 -->
<form action="process_form.php" method="post">
<input type="hidden" name="csrf_token" value="<?php echo $_SESSION['csrf_token']; ?>">
<input type="text" name="username">
<input type="submit" value="Submit">
</form>
php
// 验证 CSRF 令牌
if ($_POST['csrf_token'] !== $_SESSION['csrf_token']) {
die("CSRF token validation failed.");
}
使用 SameSite Cookie 属性:
设置 SameSite
属性为 Strict
或 Lax
,防止浏览器在跨站请求中发送 Cookie。
php
setcookie("session_id", $sessionId, [
'samesite' => 'Strict',
'secure' => true,
'httponly' => true
]);
安全的文件上传与访问控制
文件类型和大小限制:
只允许上传特定的文件类型,并限制文件的大小。
php
// 检查文件类型
$allowedTypes = ['image/jpeg', 'image/png', 'image/gif'];
if (!in_array($_FILES['file']['type'], $allowedTypes)) {
die("Invalid file type.");
}
// 检查文件大小(最大 2MB)
if ($_FILES['file']['size'] > 2 * 1024 * 1024) {
die("File is too large.");
}
文件名安全性:
对上传的文件进行重命名,避免使用原始文件名。
php
$newFileName = uniqid() . "_" . basename($_FILES["file"]["name"]);
move_uploaded_file($_FILES["file"]["tmp_name"], "uploads/" . $newFileName);
上传目录的访问控制:
- 限制对上传目录的直接访问,防止用户通过 URL 直接访问上传的文件。
- 可以在上传目录中放置一个
.htaccess
文件,禁止执行 PHP 文件。
apache
# .htaccess 文件内容
<Files *.php>
Deny from all
</Files>
避免存储敏感文件在公共目录:
如果可能,将敏感文件存储在非 Web 目录下,通过脚本访问控制下载。