php中防止SQL注入的最佳解决方法


Posted in PHP onApril 25, 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;'

我们应该怎么防止这种情况呢?下面我们来看看Theo的回答

使用预备义语句和参数化查询。对于带有任何参数的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中读取和写入WORD文档的代码
Apr 09 PHP
在服务端进行目录建立、删除,文件上传、删除的过程的php代码
Sep 10 PHP
献给php初学者(入门学习经验谈)
Oct 12 PHP
解析Extjs与php数据交互(增删查改)
Jun 25 PHP
PHP curl CURLOPT_RETURNTRANSFER参数的作用使用实例
Feb 07 PHP
php实现无限级分类(递归方法)
Aug 06 PHP
PHP程序员的技术成长规划
Mar 25 PHP
Laravel路由设定和子路由设定实例分析
Mar 30 PHP
WordPress过滤垃圾评论的几种主要方法小结
Jul 11 PHP
深入解析Laravel5.5中的包自动发现Package Auto Discovery
Sep 13 PHP
PHP实现从PostgreSQL数据库检索数据分页显示及根据条件查找数据示例
Jun 09 PHP
php判断/计算闰年的方法小结【三种方法】
Jul 06 PHP
Apache下禁止php文件被直接访问的解决方案
Apr 25 #PHP
PHP笔记之:日期函数的使用介绍
Apr 24 #PHP
php笔记之:AOP的应用
Apr 24 #PHP
php class中self,parent,this的区别以及实例介绍
Apr 24 #PHP
PHP中::、->、self、$this几种操作符的区别介绍
Apr 24 #PHP
php判断终端是手机还是电脑访问网站的思路及代码
Apr 24 #PHP
用PHP提取中英文词语以及数字的首字母的方法介绍
Apr 23 #PHP
You might like
国外PHP程序员的13个好习惯小结
2012/02/20 PHP
ecshop 批量上传(加入自定义属性)
2012/03/20 PHP
PHP实现把MySQL数据库导出为.sql文件实例(仿PHPMyadmin导出功能)
2014/05/10 PHP
PhpStorm terminal无法输入命令的解决方法
2016/10/09 PHP
phpinfo无法显示的原因及解决办法
2019/02/15 PHP
ExtJs默认的字体大小改变的几种方法(自己整理)
2013/04/18 Javascript
JQuery 获取json数据$.getJSON方法的实例代码
2013/08/02 Javascript
禁止ajax缓存获取程序最新数据的方法
2013/11/19 Javascript
jQuery的cookie插件实现保存用户登陆信息
2014/04/15 Javascript
jquery实现翻动fadeIn显示的方法
2015/03/05 Javascript
TypeScript具有的几个不同特质
2015/04/07 Javascript
js+html5实现canvas绘制圆形图案的方法
2015/06/05 Javascript
JS实现的不规则TAB选项卡效果代码
2015/09/18 Javascript
javascript巧用eval函数组装表单输入项为json对象的方法
2015/11/25 Javascript
基于jquery编写的放大镜插件
2016/03/23 Javascript
使用BootStrap建立响应式网页——通栏轮播图(carousel)
2016/12/21 Javascript
vue2.0移除或更改的一些东西(移除index key)
2017/08/28 Javascript
基于bootstrop常用类总结(推荐)
2017/09/11 Javascript
vue根据进入的路由进行原路返回的方法
2018/09/26 Javascript
zepto.js 实时监听输入框的方法
2018/12/04 Javascript
Node.js assert断言原理与用法分析
2019/01/04 Javascript
vue无限轮播插件代码实例
2019/05/10 Javascript
js中!和!!的区别与用法
2020/05/09 Javascript
使用Python脚本和ADB命令实现卸载App
2017/02/10 Python
python使用Pycharm创建一个Django项目
2018/03/05 Python
详解python如何在django中为用户模型添加自定义权限
2018/10/15 Python
python代理工具mitmproxy使用指南
2019/07/04 Python
Python自动生成代码 使用tkinter图形化操作并生成代码框架
2019/09/18 Python
python清空命令行方式
2020/01/13 Python
Python基础类继承重写实现原理解析
2020/04/03 Python
Python socket服务常用操作代码实例
2020/06/22 Python
Club Monaco加拿大官网:设计师男女服装
2019/09/29 全球购物
在C#中如何实现多态
2014/07/02 面试题
高中毕业生自我鉴定例文
2013/12/29 职场文书
2014年中班下学期工作总结
2014/12/11 职场文书
结婚保证书
2015/01/16 职场文书