PHP中防止SQL注入方法详解


Posted in PHP onDecember 25, 2014

问题描述:

如果用户输入的数据在未经处理的情况下插入到一条SQL查询语句,那么应用将很可能遭受到SQL注入攻击,正如下面的例子:

$unsafe_variable = $_POST['user_input']; 

mysql_query("INSERT INTO `table` (`column`) VALUES ('" . $unsafe_variable . "')");

因为用户的输入可能是这样的:

value'); DROP TABLE table;--

那么SQL查询将变成如下:

INSERT INTO `table` (`column`) VALUES('value'); DROP TABLE table;--')

应该采取哪些有效的方法来防止SQL注入?

 最佳回答(来自Theo):

使用预处理语句和参数化查询。预处理语句和参数分别发送到数据库服务器进行解析,参数将会被当作普通字符处理。这种方式使得攻击者无法注入恶意的SQL。 你有两种选择来实现该方法:

1、使用PDO:

$stmt = $pdo->prepare('SELECT * FROM employees WHERE name = :name');

 

$stmt->execute(array('name' => $name));

 

foreach ($stmt as $row) {

    // do something with $row

}

2、使用mysqli:

$stmt = $dbConnection->prepare('SELECT * FROM employees WHERE name = ?');

$stmt->bind_param('s', $name);

 

$stmt->execute();

 

$result = $stmt->get_result();

while ($row = $result->fetch_assoc()) {

    // do something with $row

}

 PDO

注意,在默认情况使用PDO并没有让MySQL数据库执行真正的预处理语句(原因见下文)。为了解决这个问题,你应该禁止PDO模拟预处理语句。一个正确使用PDO创建数据库连接的例子如下:

$dbConnection = new PDO('mysql:dbname=dbtest;host=127.0.0.1;charset=utf8', 'user', 'pass');

$dbConnection->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);

$dbConnection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

在上面的例子中,报错模式(ATTR_ERRMODE)并不是必须的,但建议加上它。这样,当发生致命错误(Fatal Error)时,脚本就不会停止运行,而是给了程序员一个捕获PDOExceptions的机会,以便对错误进行妥善处理。 然而,第一个setAttribute()调用是必须的,它禁止PDO模拟预处理语句,而使用真正的预处理语句,即有MySQL执行预处理语句。这能确保语句和参数在发送给MySQL之前没有被PHP处理过,这将使得攻击者无法注入恶意SQL。了解原因,可参考这篇博文:PDO防注入原理分析以及使用PDO的注意事项。 注意在老版本的PHP(<5.3.6),你无法通过在PDO的构造器的DSN上设置字符集,参考:silently ignored the charset parameter。

 解析

当你将SQL语句发送给数据库服务器进行预处理和解析时发生了什么?通过指定占位符(一个?或者一个上面例子中命名的 :name),告诉数据库引擎你想在哪里进行过滤。当你调用execute的时候,预处理语句将会与你指定的参数值结合。 关键点就在这里:参数的值是和经过解析的SQL语句结合到一起,而不是SQL字符串。SQL注入是通过触发脚本在构造SQL语句时包含恶意的字符串。所以,通过将SQL语句和参数分开,你防止了SQL注入的风险。任何你发送的参数的值都将被当作普通字符串,而不会被数据库服务器解析。回到上面的例子,如果$name变量的值为 'Sarah'; DELETE FROM employees ,那么实际的查询将是在 employees 中查找 name 字段值为 'Sarah'; DELETE FROM employees 的记录。 另一个使用预处理语句的好处是:如果你在同一次数据库连接会话中执行同样的语句许多次,它将只被解析一次,这可以提升一点执行速度。 如果你想问插入该如何做,请看下面这个例子(使用PDO):

$preparedStatement = $db->prepare('INSERT INTO table (column) VALUES (:column)');

$preparedStatement->execute(array('column' => $unsafeValue));
PHP 相关文章推荐
php+dbfile开发小型留言本
Oct 09 PHP
php下实现折线图效果的代码
Apr 28 PHP
php入门教程 精简版
Dec 13 PHP
深入php常用函数的使用汇总
Jun 08 PHP
微信扫描二维码登录网站代码示例
Dec 30 PHP
php实现文件下载简单示例(代码实现文件下载)
Mar 10 PHP
php动态生成函数示例
Mar 21 PHP
PHP实现简单的新闻发布系统实例
Jul 28 PHP
Zend Framework动作助手Url用法详解
Mar 05 PHP
PHP调用API接口实现天气查询功能的示例
Sep 21 PHP
PHP 对象继承原理与简单用法示例
Apr 21 PHP
PHPstorm启用自动换行的方法详解(IDE)
Sep 17 PHP
使用PHP实现阻止用户上传成人照片或者裸照
Dec 25 #PHP
浅析PHP文件下载原理
Dec 25 #PHP
php使用sql server验证连接数据库的方法
Dec 25 #PHP
php实现mysql事务处理的方法
Dec 25 #PHP
php使用pdo连接mssql server数据库实例
Dec 25 #PHP
php连接与操作PostgreSQL数据库的方法
Dec 25 #PHP
完整删除ecshop中获取店铺信息的API
Dec 24 #PHP
You might like
基于文本的搜索
2006/10/09 PHP
需要发散思维学习PHP
2009/06/29 PHP
《PHP编程最快明白》第五讲:php目录、文件操作
2010/11/01 PHP
php处理斐波那契数列非递归方法
2012/02/04 PHP
mac系统下为 php 添加 pcntl 扩展
2016/08/28 PHP
PHP基于curl后台远程登录正方教务系统的方法
2016/10/14 PHP
PHPExcel导出2003和2007的excel文档功能示例
2017/01/04 PHP
Thinkphp极验滑动验证码实现步骤解析
2020/11/24 PHP
javascript 实现简单的table排序及table操作练习
2012/12/28 Javascript
js解析json读取List中的实体对象示例
2014/03/11 Javascript
javascript数组操作方法小结和3个属性详细介绍
2014/07/05 Javascript
jQuery的事件委托实例分析
2015/07/15 Javascript
window.location.hash知识汇总
2015/11/09 Javascript
详解JavaScript中的自定义事件编写
2016/05/10 Javascript
两行代码轻松搞定JavaScript日期验证
2016/08/03 Javascript
Angular的事件和表单详解
2016/12/26 Javascript
es6+angular1.X+webpack 实现按路由功能打包项目的示例
2017/08/16 Javascript
Vue的路由动态重定向和导航守卫实例
2018/03/17 Javascript
JS实现读取xml内容并输出到div中的方法示例
2018/04/19 Javascript
Vue-cli配置打包文件本地使用的教程图解
2018/08/02 Javascript
layer.open 按钮的点击事件关闭方法
2018/08/17 Javascript
基于iview的router常用控制方式
2019/05/30 Javascript
微信小程序全局变量的设置、使用、修改过程解析
2019/09/24 Javascript
Vue实现腾讯云点播视频上传功能的实现代码
2020/08/17 Javascript
Django 限制访问频率的思路详解
2019/12/24 Python
Django的ListView超详细用法(含分页paginate)
2020/05/21 Python
python实现批处理文件
2020/07/28 Python
Pytorch 中的optimizer使用说明
2021/03/03 Python
推荐一些比较有用的css3新属性
2014/11/11 HTML / CSS
如何用canvas实现在线签名的示例代码
2018/07/10 HTML / CSS
外贸专业求职信
2014/03/09 职场文书
车间主任岗位职责
2014/03/16 职场文书
鼓舞士气的口号
2014/06/16 职场文书
工程部部长岗位职责
2015/02/12 职场文书
2015驻村干部工作总结
2015/04/07 职场文书
MySQL常见优化方案汇总
2022/01/18 MySQL