探讨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查看session内容的函数
Aug 27 PHP
php strcmp使用说明
Apr 22 PHP
《PHP编程最快明白》第二讲 数字、浮点、布尔型、字符串和数组
Nov 01 PHP
php安全开发 添加随机字符串验证,防止伪造跨站请求
Feb 14 PHP
thinkphp中连接oracle时封装方法无法用的解决办法
Jun 17 PHP
PHP中使用数组指针函数操作数组示例
Nov 19 PHP
PHP使用pear自带的mail类库发邮件的方法
Jul 08 PHP
YiiFramework入门知识点总结(图文教程)
Dec 28 PHP
PHP编写学校网站上新生注册登陆程序的实例分享
Mar 21 PHP
laravel migrate初学常见错误的解决方法
Oct 11 PHP
php 中phar包的使用教程详解
Oct 26 PHP
PHP的PDO大对象(LOBs)
Jan 27 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
Terran剧情介绍
2020/03/14 星际争霸
微信自定义菜单的处理开发示例
2015/04/16 PHP
PHP之图片上传类实例代码(加了缩略图)
2016/06/30 PHP
tp5.1 框架数据库高级查询技巧实例总结
2020/05/25 PHP
JavaScript事件列表解说
2006/12/22 Javascript
让浏览器DOM元素最后加载的js方法
2014/07/29 Javascript
浅析Node.js中使用依赖注入的相关问题及解决方法
2015/06/24 Javascript
JSONP跨域请求实例详解
2016/07/04 Javascript
jQuery基本过滤选择器用法示例
2016/09/09 Javascript
JS点击某个图标或按钮弹出文件选择框的实现代码
2016/09/27 Javascript
javascript 定时器工作原理分析
2016/12/03 Javascript
懒加载实现的分页&&网站footer自适应
2016/12/21 Javascript
canvas 弹幕效果(实例分享)
2017/01/11 Javascript
react性能优化达到最大化的方法 immutable.js使用的必要性
2017/03/09 Javascript
js实现rem自动匹配计算font-size的示例
2017/11/18 Javascript
jQuery实现弹窗下底部页面禁止滑动效果
2017/12/19 jQuery
详解React的回调渲染模式
2020/09/10 Javascript
Vue项目开发常见问题和解决方案总结
2020/09/11 Javascript
微信小程序实现签到弹窗动画
2020/09/21 Javascript
详解阿里Node.js技术文档之process模块学习指南
2021/01/04 Javascript
[46:49]完美世界DOTA2联赛PWL S3 access vs Rebirth 第二场 12.19
2020/12/24 DOTA
Python解析xml中dom元素的方法
2015/03/12 Python
深入理解Python中各种方法的运作原理
2015/06/15 Python
python的pdb调试命令的命令整理及实例
2017/07/12 Python
Python3.4实现从HTTP代理网站批量获取代理并筛选的方法示例
2017/09/26 Python
使用 Python 实现微信公众号粉丝迁移流程
2018/01/03 Python
python随机取list中的元素方法
2018/04/08 Python
Anaconda和ipython环境适配的实现
2020/04/22 Python
HTML5之web workers_动力节点Java学院整理
2017/07/17 HTML / CSS
高一历史教学反思
2014/01/13 职场文书
《两个铁球同时着地》教学反思
2014/02/13 职场文书
材料会计岗位职责
2014/03/06 职场文书
高中学校对照检查材料
2014/08/31 职场文书
杭州黄龙洞导游词
2015/02/10 职场文书
教师年度考核自我评鉴
2015/08/11 职场文书
mysql如何查询连续记录
2022/05/11 MySQL