您的浏览器过于古老 & 陈旧。为了更好的访问体验, 请 升级你的浏览器
CodePlayer 发布于2019年12月10日 17:13 最近更新于 2019年12月10日 18:19

在PHP中如何预防SQL注入攻击?

2981 次浏览 读完需要≈ 2 分钟 PHP

RT,在PHP中如何避免SQL注入攻击呢?

比如有如下一段PHP操作MySQL数据库的代码:

$uname = $_REQUEST['uname'];
mysql_query("INSERT INTO `my_table` (`status`, `column`) VALUES (1, '$uname')");

但是,如果前台用户发送过来的请求参数值是恶意的话,则可能导致SQL注入攻击。

举个例子,假设$uname的值为张三'); DROP TABLE my_table;--,则最终形成的SQL命名实际为:

INSERT INTO `my_table` (`status`, `column`) VALUES (1, '张三'); DROP TABLE my_table;--

这种情况,好像就有可能直接将数据表删除掉。

请问怎样才能避免这种SQL注入呢?

1 个回答

Ready · 4年前

PDO

在 PHP 中应该首选 PDO 方式来进行数据库访问操作。

在老版本的PHP中,PHP要访问不同的数据库,各系列的 操作 API 也是各不相同的。

比如,要访问MySQL,就是 mysql_connect()mysql_query()mysql_close()……

如果要访问 Microsoft SQL Server,就是 mssql_connect()mssql_query()mssql_close()……

如果要访问 Oracle,就是 oci_connect()oci_query()oci_close()……

采用这种方式,如果需要切换到另一个不同类型的数据库,就必须要用另外一套函数重新写一套数据访问代码——尽管它们看起来非常相似。

于是从PHP 5 开始(外置的Perl模块,从 PHP 5.1 开始内置),官方推出了 PDO,我们只需要用同一套API,然后进行不同的数据源连接配置,即可访问不同类型的数据库。

这里我们不过多介绍,大家可以直接去参考官方的中文文档。先解决你提出的问题:

$uname = $_REQUEST['uname'];

$pdo = new PDO('mysql:host=localhost;port=3306;dbname=test;charset=utf8', 'username', 'password');
$stmt = $pdo->prepare('INSERT INTO `my_table` (`status`, `column`) VALUES (1, ?)');
$stmt->execute(array($uname));
foreach ($stmt as $row) {
	// do something with $row
}

上面SQL语句中的?就是一个绑定的SQL参数占位符。

mysqli

如果你的 PHP 版本比较低(比如 PHP 4),那么你也可以使用 mysqli 系列函数库,它是 mysql 函数库的增强版,也可以和 PDO 一样通过?参数占位符的形式来避免SQL注入攻击。

$uname = $_REQUEST['uname'];

$conn = mysqli_connect('localhost', 'user', 'password', 'test'));
$stmt = $conn->prepare('INSERT INTO `my_table` (`status`, `column`) VALUES (1, ?)');
$stmt->bind_param('s', $uname);
// 's' 表示是字符串类型,还有 'i' 表示整数,'d' 表示小数, 'b' 表示二进制数据
$stmt->execute();
$result = $stmt->get_result();
while ($row = $result->fetch_assoc()) {
	// do something with $row
}

1、请自行注意异常处理
2、如果是数字或其他有特定格式的数据,请最好在访问数据库之前进行预校验。
3、更多细节请参见官方文档,这里只是抛砖引玉。

撰写答案