搜索
首页php教程php手册Php中用PDO查询Mysql来避免SQL注入风险的方法
Php中用PDO查询Mysql来避免SQL注入风险的方法Jun 13, 2016 am 11:53 AM
cmysqlpdophpsql使用我们方法查询注入避免风险

当我们使用传统的 mysql_connect 、mysql_query方法来连接查询数据库时,如果过滤不严,就有SQL注入风险,导致网站被攻击,失去控制。虽然可以用mysql_real_escape_string()函数过滤用户提交的值,但是也有缺陷。而使用PHP的PDO扩展的 prepare 方法,就可以避免sql injection 风险。

PDO(PHP Data Object) 是PHP5新加入的一个重大功能,因为在PHP 5以前的php4/php3都是一堆的数据库扩展来跟各个数据库的连接和处理,如 php_mysql.dll。 PHP6中也将默认使用PDO的方式连接,mysql扩展将被作为辅助 。官方:http://php.net/manual/en/book.pdo.php

1、PDO配置
使用PDO扩展之前,先要启用这个扩展,PHP.ini中,去掉"extension=php_pdo.dll"前面的";"号,若要连接数据库,还需要去掉与PDO相关的数据库扩展前面的";"号(一般用的是php_pdo_mysql.dll),然后重启Apache服务器即可。

复制代码 代码如下:


extension=php_pdo.dll
extension=php_pdo_mysql.dll


2、PDO连接mysql数据库

复制代码 代码如下:


$dbh = new PDO("mysql:host=localhost;dbname=db_demo","root","password");


默认不是长连接,若要使用数据库长连接,需要在最后加如下参数:

复制代码 代码如下:


$dbh = new PDO("mysql:host=localhost;dbname=db_demo","root","password","array(PDO::ATTR_PERSISTENT => true)");
$dbh = null; //(释放)


3、PDO设置属性

1) PDO有三种错误处理方式:

• PDO::ERrmODE_SILENT不显示错误信息,只设置错误码
• PDO::ERrmODE_WARNING显示警告错
• PDO::ERrmODE_EXCEPTION抛出异常

可通过以下语句来设置错误处理方式为抛出异常

复制代码 代码如下:


$db->setAttribute(PDO::ATTR_ERrmODE, PDO::ERrmODE_EXCEPTION);


当设置为PDO::ERrmODE_SILENT时可以通过调用errorCode() 或errorInfo()来获得错误信息,当然其他情况下也可以。

2) 因为不同数据库对返回的字段名称大小写处理不同,所以PDO提供了PDO::ATTR_CASE设置项(包括PDO::CASE_LOWER,PDO::CASE_NATURAL,PDO::CASE_UPPER),来确定返回的字段名称的大小写。

3) 通过设置PDO::ATTR_ORACLE_NULLS类型(包括PDO::NULL_NATURAL,PDO::NULL_EmpTY_STRING,PDO::NULL_TO_STRING)来指定数据库返回的NULL值在php中对应的数值。

4、PDO常用方法及其应用
PDO::query() 主要是用于有记录结果返回的操作,特别是SELECT操作
PDO::exec() 主要是针对没有结果集合返回的操作,如INSERT、UPDATE等操作
PDO::prepare() 主要是预处理操作,需要通过$rs->execute()来执行预处理里面的SQL语句,这个方法可以绑定参数,功能比较强大(防止sql注入就靠这个)
PDO::lastInsertId() 返回上次插入操作,主键列类型是自增的最后的自增ID
PDOStatement::fetch() 是用来获取一条记录
PDOStatement::fetchAll() 是获取所有记录集到一个集合
PDOStatement::fetchColumn() 是获取结果指定第一条记录的某个字段,缺省是第一个字段
PDOStatement::rowCount() :主要是用于PDO::query()和PDO::prepare()进行DELETE、INSERT、UPDATE操作影响的结果集,对PDO::exec()方法和SELECT操作无效。

5、PDO操作MYSQL数据库实例

复制代码 代码如下:


$pdo = new PDO("mysql:host=localhost;dbname=db_demo","root","");
if($pdo -> exec("insert into db_demo(name,content) values('title','content')")){
echo "插入成功!";
echo $pdo -> lastinsertid();
}
?>


复制代码 代码如下:


$pdo = new PDO("mysql:host=localhost;dbname=db_demo","root","");
$rs = $pdo -> query("select * from test");
$rs->setFetchMode(PDO::FETCH_ASSOC); //关联数组形式
//$rs->setFetchMode(PDO::FETCH_NUM); //数字索引数组形式
while($row = $rs -> fetch()){
print_r($row);
}
?>


复制代码 代码如下:


foreach( $db->query( "SELECT * FROM feeds" ) as $row )
{
    print_r( $row );
}
?>


统计有多少行数据

复制代码 代码如下:


$sql="select count(*) from test";
$num = $dbh->query($sql)->fetchColumn();


prepare方式

复制代码 代码如下:


$stmt = $dbh->prepare("select * from test");
if ($stmt->execute()) {
 while ($row = $stmt->fetch()) {
     print_r($row);
 }
}


Prepare参数化查询

复制代码 代码如下:


$stmt = $dbh->prepare("select * from test where name = ?");
if ($stmt->execute(array("david"))) {
 while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
     print_r($row);
 }
}


【下面来说说重点了,如何防止 sql注入】

使用PDO访问MySQL数据库时,真正的real prepared statements 默认情况下是不使用的。为了解决这个问题,你必须禁用 prepared statements的仿真效果。下面是使用PDO创建链接的例子:

复制代码 代码如下:


$dbh = new PDO('mysql:dbname=dbtest;host=127.0.0.1;charset=utf8', 'user', 'pass');
$dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);


setAttribute()这一行是强制性的,它会告诉 PDO 禁用模拟预处理语句,并使用 real parepared statements 。这可以确保SQL语句和相应的值在传递到mysql服务器之前是不会被PHP解析的(禁止了所有可能的恶意SQL注入攻击)。虽然你可以配置文件中设置字符集的属性(charset=utf8),但是需要格外注意的是,老版本的 PHP(

我们来看一段完整的代码使用实例:

复制代码 代码如下:


$dbh = new PDO("mysql:host=localhost; dbname=demo", "user", "pass");
$dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, false); //禁用prepared statements的仿真效果
$dbh->exec("set names 'utf8'");
$sql="select * from test where name = ? and password = ?";
$stmt = $dbh->prepare($sql);
$exeres = $stmt->execute(array($testname, $pass));
if ($exeres) {
 while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
     print_r($row);
 }
}
$dbh = null;


上面这段代码就可以防范sql注入。为什么呢?

当调用 prepare() 时,查询语句已经发送给了数据库服务器,此时只有占位符 ? 发送过去,没有用户提交的数据;当调用到 execute()时,用户提交过来的值才会传送给数据库,他们是分开传送的,两者独立的,SQL攻击者没有一点机会。

但是我们需要注意的是以下几种情况,PDO并不能帮助你防范SQL注入

1、你不能让占位符 ? 代替一组值,如:

复制代码 代码如下:


SELECT * FROM blog WHERE userid IN ( ? );


2、你不能让占位符代替数据表名或列名,如:

复制代码 代码如下:


SELECT * FROM blog ORDER BY ?;


3、你不能让占位符 ? 代替任何其他SQL语法,如:

复制代码 代码如下:


SELECT EXTRACT( ? FROM datetime_column) AS variable_datetime_element FROM blog;


声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
php怎么把负数转为正整数php怎么把负数转为正整数Apr 19, 2022 pm 08:59 PM

php把负数转为正整数的方法:1、使用abs()函数将负数转为正数,使用intval()函数对正数取整,转为正整数,语法“intval(abs($number))”;2、利用“~”位运算符将负数取反加一,语法“~$number + 1”。

php怎么实现几秒后执行一个函数php怎么实现几秒后执行一个函数Apr 24, 2022 pm 01:12 PM

实现方法:1、使用“sleep(延迟秒数)”语句,可延迟执行函数若干秒;2、使用“time_nanosleep(延迟秒数,延迟纳秒数)”语句,可延迟执行函数若干秒和纳秒;3、使用“time_sleep_until(time()+7)”语句。

php怎么除以100保留两位小数php怎么除以100保留两位小数Apr 22, 2022 pm 06:23 PM

php除以100保留两位小数的方法:1、利用“/”运算符进行除法运算,语法“数值 / 100”;2、使用“number_format(除法结果, 2)”或“sprintf("%.2f",除法结果)”语句进行四舍五入的处理值,并保留两位小数。

php怎么根据年月日判断是一年的第几天php怎么根据年月日判断是一年的第几天Apr 22, 2022 pm 05:02 PM

判断方法:1、使用“strtotime("年-月-日")”语句将给定的年月日转换为时间戳格式;2、用“date("z",时间戳)+1”语句计算指定时间戳是一年的第几天。date()返回的天数是从0开始计算的,因此真实天数需要在此基础上加1。

php怎么替换nbsp空格符php怎么替换nbsp空格符Apr 24, 2022 pm 02:55 PM

方法:1、用“str_replace(" ","其他字符",$str)”语句,可将nbsp符替换为其他字符;2、用“preg_replace("/(\s|\&nbsp\;||\xc2\xa0)/","其他字符",$str)”语句。

php怎么判断有没有小数点php怎么判断有没有小数点Apr 20, 2022 pm 08:12 PM

php判断有没有小数点的方法:1、使用“strpos(数字字符串,'.')”语法,如果返回小数点在字符串中第一次出现的位置,则有小数点;2、使用“strrpos(数字字符串,'.')”语句,如果返回小数点在字符串中最后一次出现的位置,则有。

php字符串有没有下标php字符串有没有下标Apr 24, 2022 am 11:49 AM

php字符串有下标。在PHP中,下标不仅可以应用于数组和对象,还可应用于字符串,利用字符串的下标和中括号“[]”可以访问指定索引位置的字符,并对该字符进行读写,语法“字符串名[下标值]”;字符串的下标值(索引值)只能是整数类型,起始值为0。

php怎么读取字符串后几个字符php怎么读取字符串后几个字符Apr 22, 2022 pm 08:31 PM

在php中,可以使用substr()函数来读取字符串后几个字符,只需要将该函数的第二个参数设置为负值,第三个参数省略即可;语法为“substr(字符串,-n)”,表示读取从字符串结尾处向前数第n个字符开始,直到字符串结尾的全部字符。

See all articles

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热门文章

R.E.P.O.能量晶体解释及其做什么(黄色晶体)
2 周前By尊渡假赌尊渡假赌尊渡假赌
仓库:如何复兴队友
4 周前By尊渡假赌尊渡假赌尊渡假赌
Hello Kitty Island冒险:如何获得巨型种子
4 周前By尊渡假赌尊渡假赌尊渡假赌

热工具

WebStorm Mac版

WebStorm Mac版

好用的JavaScript开发工具

MinGW - 适用于 Windows 的极简 GNU

MinGW - 适用于 Windows 的极简 GNU

这个项目正在迁移到osdn.net/projects/mingw的过程中,你可以继续在那里关注我们。MinGW:GNU编译器集合(GCC)的本地Windows移植版本,可自由分发的导入库和用于构建本地Windows应用程序的头文件;包括对MSVC运行时的扩展,以支持C99功能。MinGW的所有软件都可以在64位Windows平台上运行。

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

Atom编辑器mac版下载

Atom编辑器mac版下载

最流行的的开源编辑器

SublimeText3 英文版

SublimeText3 英文版

推荐:为Win版本,支持代码提示!