探讨php中防止SQL注入最好的方法是什么


Posted in PHP onJune 10, 2013

如果用户输入的是直接插入到一个SQL语句中的查询,应用程序会很容易受到SQL注入,例如下面的例子:

$unsafe_variable = $_POST['user_input'];
mysql_query("INSERT INTO table (column) VALUES ('" . $unsafe_variable . "')");

这是因为用户可以输入类似VALUE“); DROP TABLE表; - ,使查询变成:
INSERT INTO table (column) VALUES('VALUE'); DROP TABLE table;'

我们应该怎么防止这种情况呢?请看下面
使用预备义语句和参数化查询。对于带有任何参数的sql语句都会被发送到数据库服务器,并被解析!对于攻击者想要恶意注入sql是不可能的!
实现这一目标基本上有两种选择:
1.使用PDO(PHP Data Objects ):
$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(PHP数据对象)
注意当使用PDO访问MySQL数据库真正的预备义语句并不是默认使用的!为了解决这个问题,你必须禁用仿真准备好的语句。
使用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);

在上面例子中错误模式ERRMODE不是严格必须的,但是建议添加它。当运行出错产生致命错误时,这种方法脚本不会停止。并给开发人员捕捉任何错误的机会(当抛出PDOException异常时)。
setAttribute()那一行是强制性的,它告诉PDO禁用仿真预备义语句,使用真正的预备义语句。这可以确保语句和值在发送给MySQL数据库服务器前不被PHP解析(攻击者没有机会注入恶意的SQL).
当然你可以在构造函数选项中设置字符集参数,特别注意'老'的PHP版本(5.3.6)会在DSN中忽略掉字符集参数。

Explanation(解释)
在你传递的sql预备义语句 被数据库服务器解析和编译会发生什么?通过指定的字符(在上面例子中像a?或者像:name)告诉数据库引擎你想要过滤什么.然后调用execute执行结合好的预备义语句和你指定的参数值.

这里最重要的是,该参数值是和预编译的语句结合的,而不是和一个SQL字符串.SQL注入的工作原理是通过欺骗手段创建的SQL脚本包括恶意字符串发送到数据库.因此,通过发送实际的分开的sql参数,你会降低风险.使用准备好的语句时,你发送的任何参数,将只被视为字符串(虽然数据库引擎可能会做一些参数的优化,当然最终可能会为数字).在上面的例子中,如果变量$name包含'sarah';DELETE * FROM employees,结果只会是一个搜索的字符串"'sarah';DELETE * FROM employees",你不会得到一个空表。

使用准备好的语句的另一个好处是,如果你在同一会话中多次执行相同的语句,这将只被解析和编译一次,给你一些的速度增长。
哦,既然你问如何进行插入,这里是一个例子(使用PDO):

$preparedStatement = $db->prepare('INSERT INTO table (column) VALUES (:column)');
$preparedStatement->execute(array(':column' => $unsafeValue));
PHP 相关文章推荐
php中获取远程客户端的真实ip地址的方法
Aug 03 PHP
PHP使用数组实现队列
Feb 05 PHP
用PHP实现浏览器点击下载TXT文档的方法详解
Jun 02 PHP
php ci框架验证码实例分析
Jun 26 PHP
PHP实现根据浏览器跳转不同语言页面代码
Aug 02 PHP
2个自定义的PHP in_array 函数,解决大量数据判断in_array的效率问题
Apr 08 PHP
PHP网页游戏学习之Xnova(ogame)源码解读(十一)
Jun 25 PHP
浅析get与post的一些特殊情况
Jul 28 PHP
win10环境PHP 7 安装配置【教程】
May 09 PHP
PHP实现的pdo连接数据库并插入数据功能简单示例
Mar 30 PHP
thinkphp5使html5实现动态跳转的例子
Oct 16 PHP
Yii框架模拟组件调用注入示例
Nov 11 PHP
php防注入,表单提交值转义的实现详解
Jun 10 #PHP
PHP获取当前页面完整URL的实现代码
Jun 10 #PHP
如何判断php数组的维度
Jun 10 #PHP
joomla jce editor 解决上传中文名文件失败问题
Jun 09 #PHP
php缩放图片(根据宽高的等比例缩放)实例介绍
Jun 09 #PHP
探讨php define()函数及defined()函数使用详解
Jun 09 #PHP
如何用php获取程序执行的时间
Jun 09 #PHP
You might like
跟我学小偷程序之成功偷取首页(第三天)
2006/10/09 PHP
php中的时间显示
2007/01/18 PHP
hessian 在PHP中的使用介绍
2010/12/13 PHP
php xml 入门学习资料
2011/01/01 PHP
解析PHP 5.5 新特性
2013/07/02 PHP
Js如何判断客户端是PC还是手持设备简单分析
2012/11/22 Javascript
jquery表格内容筛选实现思路及代码
2013/04/16 Javascript
jquery实现select选中行、列合计示例
2014/04/25 Javascript
jquery等待效果示例
2014/05/01 Javascript
IE中图片的onload事件无效问题和解决方法
2014/06/06 Javascript
详谈javascript中DOM的基本属性
2015/02/26 Javascript
基于jQuery实现简单的折叠菜单效果
2015/11/23 Javascript
JS获取屏幕高度的简单实现代码
2016/05/24 Javascript
jQuery实现立体式数字动态增加(animate方法)
2016/12/21 Javascript
利用SpringMVC过滤器解决vue跨域请求的问题
2018/02/10 Javascript
Vue自定义弹窗指令的实现代码
2018/08/13 Javascript
Angular刷新当前页面的实现方法
2018/11/21 Javascript
Node.js学习教程之Module模块
2019/09/03 Javascript
详解JavaScript之ES5的继承
2020/07/08 Javascript
Python ORM框架SQLAlchemy学习笔记之安装和简单查询实例
2014/06/10 Python
Python读取Json字典写入Excel表格的方法
2018/01/03 Python
Python使用__new__()方法为对象分配内存及返回对象的引用示例
2019/09/20 Python
python3连接MySQL8.0的两种方式
2020/02/17 Python
Python实现图片查找轮廓、多边形拟合、最小外接矩形代码
2020/07/14 Python
Python抖音快手代码舞(字符舞)的实现方法
2021/02/07 Python
python解包用法详解
2021/02/17 Python
Python Selenium操作Cookie的实例方法
2021/02/28 Python
全球领先的中国制造商品在线批发平台:DHgate
2020/01/28 全球购物
掌上明珠Java程序员面试总结
2016/02/23 面试题
顶岗实习接收函
2014/01/09 职场文书
市场部管理制度
2014/02/02 职场文书
公司演讲稿开场白
2014/08/25 职场文书
企业总经理助理岗位职责
2014/09/12 职场文书
新生开学寄语大全
2015/05/28 职场文书
观后感开头
2015/06/19 职场文书
旅游投诉信范文
2015/07/02 职场文书