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

2次阅读

防止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