如何防止sql注入_mysql项目安全写法

12次阅读

防止 SQL 注入的核心是禁用用户输入拼接,必须使用预处理语句(PDO/MySQLi 参数化查询),辅以输入校验、最小权限原则和安全配置,杜绝直接拼接、废弃函数及动态标识符。

如何防止 sql 注入_mysql 项目安全写法

防止 SQL 注入的核心是:永远不要把用户输入直接拼接到 SQL 语句中。MySQL 项目中,最可靠、最推荐的做法是使用 预处理语句(Prepared Statements)配合参数化查询,同时辅以输入校验和权限控制。

用 PDO 或 MySQLi 的预处理机制

这是防御 SQL 注入的黄金标准。数据库驱动会自动区分“SQL 结构”和“数据内容”,从根本上杜绝恶意代码执行。

  • PDO 示例(推荐):
    $pdo = new PDO("mysql:host=localhost;dbname=test", $user, $pass);
    $stmt = $pdo->prepare("SELECT * FROM users WHERE username = ? AND status = ?");
    $stmt->execute([$username, $status]); // 自动转义,类型安全
  • MySQLi 面向对象示例:
    $mysqli = new mysqli("localhost", $user, $pass, "test");
    $stmt = $mysqli->prepare("INSERT INTO logs (ip, action) VALUES (?, ?)");
    $stmt->bind_param("ss", $client_ip, $action); // s=string, i=integer
    $stmt->execute();

严格过滤和验证用户输入

预处理不能替代业务层校验。对输入做白名单式约束,能提前拦截异常请求,降低攻击面。

  • 数字类字段(如 ID、分页页码):用 (int) 强转或 filter_var($input, FILTER_VALIDATE_INT)
  • 邮箱、URL、手机号等:使用 filter_var() 对应过滤器,例如 filter_var($email, FILTER_VALIDATE_EMAIL)
  • 用户名、标题等字符串:限制长度、禁止特殊字符(如 /^[a-zA-Z0-9_x{4e00}-x{9fa5}]{2,20}$/u),避免正则回溯漏洞
  • 绝不信任 前端 传来的任何值——包括 hidden input、cookie、header 中的数据

最小权限原则与数据库配置加固

即使某条语句被绕过,限制数据库账户权限也能大幅降低危害。

  • Web 应用连接 MySQL 时,使用专用账号,只授予必要权限:
    GRANT SELECT, INSERT, UPDATE ON mydb.users TO 'webapp'@'localhost';
    禁用 DROPDELETECREATELOAD_FILE 等高危权限
  • 关闭 MySQL 的 local_infile(防止利用 LOAD DATA INFILE 读取服务器文件)
  • 生产环境禁用错误信息外泄:PHP 中设 display_errors = Off,MySQL 中避免返回详细报错(如 mysqli_report(MYSQLI_REPORT_OFF)

避免已淘汰或不安全的写法

这些方式看似简单,但极易引入风险,务必替换掉:

  • "SELECT * FROM users WHERE id =" . $_GET['id'] —— 直接拼接,高危
  • mysql_real_escape_string()(已废弃)或 addslashes() —— 无法覆盖所有 编码 绕过场景,不推荐
  • ❌ 动态构建表名 / 字段名(如 "SELECT * FROM" . $_POST['table'])—— 预处理不支持占位符用于标识符,必须用白名单映射
  • ✅ 正确做法:表名 / 字段名由程序内定义数组控制,例如 $allowed_tables = ['users', 'orders']; if (!in_array($table, $allowed_tables)) die('Invalid table');

text=ZqhQzanResources