探讨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中用hash实现的数组
Jul 17 PHP
php 阴历-农历-转换类代码
Jan 16 PHP
浅谈PHP变量作用域以及地址引用问题
Dec 27 PHP
php中$美元符号与Zen Coding冲突问题解决方法分享
May 28 PHP
php关联数组快速排序的方法
Apr 17 PHP
PHP 使用 Imagick 裁切/生成缩略图/添加水印自动检测和处理 GIF
Feb 19 PHP
100多行PHP代码实现socks5代理服务器[2]
May 05 PHP
php简单统计在线人数的方法
May 10 PHP
PHP中有关长整数的一些操作教程
Sep 11 PHP
php设计模式之观察者模式定义与用法经典示例
Sep 19 PHP
PHP实用小技巧之调用录像的方法
Dec 05 PHP
YII2框架中添加自定义模块的方法实例分析
Mar 18 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
Destoon模板制作简明教程
2014/06/20 PHP
PHP计算日期相差天数实例分析
2016/02/23 PHP
PHP实现网页内容html标签补全和过滤的方法小结【2种方法】
2017/04/27 PHP
PHP array_shift()用法实例分析
2019/01/07 PHP
浅谈PHP匿名函数和闭包
2019/03/08 PHP
Jquery 基础学习笔记之文档处理
2009/05/29 Javascript
CSS(js)限制页面显示的文本字符长度
2012/12/27 Javascript
点击标签切换和自动切换DIV选项卡
2014/08/10 Javascript
推荐5 个常用的JavaScript调试技巧
2015/01/08 Javascript
jquery form表单获取内容以及绑定数据
2016/02/24 Javascript
vue分页组件table-pagebar使用实例解析
2020/11/15 Javascript
JS实现鼠标滑过显示边框的菜单效果
2016/09/21 Javascript
浅谈Web页面向后台提交数据的方式和选择
2016/09/23 Javascript
js返回顶部实例分享
2016/12/21 Javascript
jquery在vue脚手架中的使用方式示例
2017/08/29 jQuery
Vue常用指令详解分析
2018/08/19 Javascript
ES6 如何改变JS内置行为的代理与反射
2019/02/11 Javascript
深入解析koa之异步回调处理
2019/06/17 Javascript
通过说明与示例了解js五种设计模式
2019/06/17 Javascript
H5 js点击按钮复制文本到粘贴板
2020/11/19 Javascript
python字典值排序并取出前n个key值的方法
2018/10/17 Python
python之信息加密题目详解
2019/06/26 Python
Pyinstaller 打包发布经验总结
2020/06/02 Python
Myprotein加拿大官网:欧洲第一的运动营养品牌
2018/01/06 全球购物
西班牙最大的在线滑板和街头服饰商店:Fillow.net
2019/04/15 全球购物
企事业单位求职者的自我评价
2013/12/28 职场文书
会计专业自我鉴定范文
2013/12/29 职场文书
初中学生期末评语
2014/04/24 职场文书
大学新生入学教育方案
2014/05/16 职场文书
施工员岗位职责
2015/02/10 职场文书
会计简历自我评价
2015/03/10 职场文书
给校长的建议书作文500字
2015/09/14 职场文书
小学运动会开幕词
2016/03/04 职场文书
技术入股合作协议书
2016/03/21 职场文书
巧用 -webkit-box-reflect 倒影实现各类动效(小结)
2021/04/22 HTML / CSS
MySQL中int (10) 和 int (11) 的区别
2022/01/22 MySQL