本文目录导读:

我来通过一个用户登录系统的案例,演示PHP如何防止SQL注入攻击。
不安全的代码示例(容易受到SQL注入攻击)
<?php
// 不安全的登录验证
$username = $_POST['username'];
$password = $_POST['password'];
// 直接拼接SQL语句 - 非常危险!
$sql = "SELECT * FROM users WHERE username = '$username' AND password = '$password'";
$result = mysqli_query($conn, $sql);
if (mysqli_num_rows($result) > 0) {
echo "登录成功";
} else {
echo "登录失败";
}
?>
攻击者可以输入:
- 用户名:
admin' -- - 密码:
这会变成:SELECT * FROM users WHERE username = 'admin' --' AND password = '...',绕过了密码验证!
安全的代码示例(使用预处理语句)
<?php
// 安全的登录验证 - 使用PDO预处理语句
// 数据库连接配置
$host = 'localhost';
$dbname = 'user_system';
$username = 'root';
$password = '';
try {
// 创建PDO连接
$pdo = new PDO("mysql:host=$host;dbname=$dbname;charset=utf8mb4", $username, $password);
// 设置错误模式为异常
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
// 获取用户输入
$userInput = $_POST['username'];
$passInput = $_POST['password'];
// 使用预处理语句(推荐方式)
$stmt = $pdo->prepare("SELECT * FROM users WHERE username = :username AND password = :password");
// 绑定参数(自动处理转义)
$stmt->bindParam(':username', $userInput, PDO::PARAM_STR);
$stmt->bindParam(':password', $passInput, PDO::PARAM_STR);
// 执行查询
$stmt->execute();
// 获取结果
$user = $stmt->fetch(PDO::FETCH_ASSOC);
if ($user) {
// 使用password_verify验证密码哈希(更安全)
if (password_verify($passInput, $user['password'])) {
echo "登录成功!欢迎 " . htmlspecialchars($user['username']);
} else {
echo "密码错误";
}
} else {
echo "用户不存在";
}
} catch (PDOException $e) {
// 记录错误但不显示敏感信息给用户
error_log("数据库错误: " . $e->getMessage());
echo "系统错误,请稍后再试";
}
?>
更完整的注册和登录示例
<?php
class SecureUserAuth {
private $pdo;
public function __construct($host, $dbname, $username, $password) {
$dsn = "mysql:host=$host;dbname=$dbname;charset=utf8mb4";
$this->pdo = new PDO($dsn, $username, $password, [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => false // 使用真实的预处理语句
]);
}
// 安全注册
public function register($username, $password) {
// 参数验证
if (strlen($username) < 3 || strlen($username) > 20) {
return "用户名长度必须在3-20之间";
}
if (strlen($password) < 6) {
return "密码长度至少6位";
}
try {
// 检查用户名是否已存在(使用预处理语句)
$checkStmt = $this->pdo->prepare("SELECT id FROM users WHERE username = :username");
$checkStmt->execute([':username' => $username]);
if ($checkStmt->fetch()) {
return "用户名已存在";
}
// 密码哈希(绝不要明文存储密码)
$hashedPassword = password_hash($password, PASSWORD_DEFAULT);
// 安全插入数据
$insertStmt = $this->pdo->prepare(
"INSERT INTO users (username, password, created_at) VALUES (:username, :password, NOW())"
);
$insertStmt->execute([
':username' => $username,
':password' => $hashedPassword
]);
return "注册成功";
} catch (PDOException $e) {
error_log("注册错误: " . $e->getMessage());
return "注册失败,请稍后重试";
}
}
// 搜索功能(同样是安全的)
public function searchUsers($keyword) {
// 使用LIKE查询也安全
$stmt = $this->pdo->prepare(
"SELECT id, username FROM users WHERE username LIKE :keyword LIMIT 10"
);
// LIKE查询需要特殊处理
$searchTerm = '%' . $keyword . '%';
$stmt->execute([':keyword' => $searchTerm]);
return $stmt->fetchAll();
}
}
// 使用示例
$auth = new SecureUserAuth('localhost', 'user_system', 'root', 'password');
// 安全注册
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['register'])) {
$result = $auth->register($_POST['username'], $_POST['password']);
echo $result;
}
// 安全搜索
if (isset($_GET['search'])) {
$users = $auth->searchUsers($_GET['keyword']);
foreach ($users as $user) {
echo htmlspecialchars($user['username']) . "<br>";
}
}
?>
数据库表结构
CREATE TABLE users (
id INT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(50) NOT NULL UNIQUE,
password VARCHAR(255) NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
关键防护措施总结
- 使用预处理语句(PDO或MySQLi) - 最有效的防御
- 参数绑定 - 避免直接拼接SQL
- 密码哈希 - 使用
password_hash()和password_verify() - 输入验证 - 检查数据类型、长度、格式
- 输出转义 - 使用
htmlspecialchars()防止XSS - 最小权限原则 - 数据库用户只授予必要的权限
- 错误处理 - 不向用户显示敏感错误信息
通过这种方式,即使攻击者输入 ' OR '1'='1 这样的恶意内容,预处理语句也会将其视为普通字符串,不会影响SQL语句的结构。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播