这篇是上一篇 http://www.cnblogs.com/charlesblc/p/5987951.html 的续集。

看有的文章提到mysqli和PDO都支持多重查询,所以下面的url会造成表数据被删。

http://localhost:8080/test.php?id=3;delete%20from%20users

可是我在mysql版本的函数,上面的sql都不能执行。是不是不支持多重查询了?

这篇文章 http://www.runoob.com/php/php-mysql-connect.html 对mysqli, PDO的方式有一些介绍,不详细。

主要用的这篇文章:http://blog.csdn.net/yipiankongbai/article/details/17277477

三种连接方式:

// PDO
$pdo = new PDO("mysql:host=localhost;dbname=database", 'username', 'password'); // mysqli, procedural way
$mysqli = mysqli_connect('localhost','username','password','database'); // mysqli, object oriented way
$mysqli = new mysqli('localhost','username','password','database');

先看mysqli过程型:

<?php
header('Content-Type: text/html; charset=utf-8');
echo "PHP version:" . PHP_VERSION . "<br/>"; $con = mysqli_connect('10.117.146.21:8306', 'root', '[password]');
mysqli_select_db($con, 'springdemo'); $input_id = trim($_GET['id']);
$sql = 'select nickname from user where id = ' . $input_id;
print_r('SQL is:' . $sql . '<br/>');
$result = mysqli_query($con, $sql); if ($result != null) {
print_r('rows:' . mysqli_num_rows($result) . '<br/>');
while ($row = mysqli_fetch_array($result)) {
print_r($row['nickname'] . '<br/>');
}
} mysqli_close($con);
?>

测试:

http://localhost:8080/test.php?id=3

PHP version:5.5.30
SQL is:select nickname from user where id = 3
rows:1
micro http://localhost:8080/test.php?id=3%20or%201=1 PHP version:5.5.30
SQL is:select nickname from user where id = 3 or 1=1
rows:4
abc
micro
helloworld
你好

加上real_escape函数:

?php
header('Content-Type: text/html; charset=utf-8');
echo "PHP version:" . PHP_VERSION . "<br/>"; $con = mysqli_connect('10.117.146.21:8306', 'root', '[password]');
mysqli_select_db($con, 'springdemo'); $input_id = mysqli_real_escape_string($con, $_GET['id']);
$sql = 'select nickname from user where id = ' . $input_id;
print_r('SQL is:' . $sql . '<br/>');
$result = mysqli_query($con, $sql); if ($result != null) {
print_r('rows:' . mysqli_num_rows($result) . '<br/>');
while ($row = mysqli_fetch_array($result)) {
print_r($row['nickname'] . '<br/>');
}
} mysqli_close($con);
?>

测试:

http://localhost:8080/test.php?id=3%20or%201=1

PHP version:5.5.30
SQL is:select nickname from user where id = 3 or 1=1
rows:4
abc
micro
helloworld
你好 注:仍然有问题,因为没有在url里面加引号!

采用推荐的mysqli的PreparedStatement方式:

?php
header('Content-Type: text/html; charset=utf-8');
echo "PHP version:" . PHP_VERSION . "<br/>"; $con = new mysqli('10.117.146.21:8306', 'root', '[password]', 'springdemo');
//mysqli_select_db($con, 'springdemo'); $query = $con->prepare('SELECT nickname FROM user WHERE id = ?');
$query->bind_param('s', $_GET['id']);
$query->execute(); $result = $query->get_result();
if ($result != null) {
print_r('rows:' . mysqli_num_rows($result) . '<br/>');
while ($row = mysqli_fetch_array($result)) {
print_r($row['nickname'] . '<br/>');
}
} mysqli_close($con);
?>

测试:

http://localhost:8080/test.php?id=3

PHP version:5.5.30
rows:1
micro http://localhost:8080/test.php?id=3%20or%201=1 PHP version:5.5.30
rows:1
micro

PDO与mysqli的对比:

性能
PDO和MySQLi都有非常好的性能。在非prepared statements的基准测试下,MySQLi略快2.5%,而prepared statements下是6.5%,可以说对于性能无关紧要。
  PDO MySQLi
Database support 12 different drivers MySQL only
API OOP OOP + procedural
Connection Easy Easy
Named parameters Yes No
Object mapping Yes Yes
Prepared statements 
(client side)
Yes No
Performance Fast Fast
Stored procedures Yes Yes

PDO方式:

<?php
header('Content-Type: text/html; charset=utf-8');
echo "PHP version:" . PHP_VERSION . "<br/>"; $pdo = new PDO("mysql:host=10.117.146.21:8306;dbname=springdemo", 'root', '[password]'); class Name {
public $nickname; public function info()
{
return '#'.$this->nickname;
}
} $input_id = $_GET['id'];
$sql = 'select nickname from user where id = ' . $input_id;
print_r('SQL is:' . $sql . '<br/>');
$result = $pdo->query($sql);
$result->setFetchMode(PDO::FETCH_CLASS, 'Name'); if ($result != null) {
while ($row = $result->fetch()) {
print_r($row->info() . '<br/>');
}
} $pdo=null;
?>

测试:

http://localhost:8080/test.php?id=3

PHP version:5.5.30
SQL is:select nickname from user where id = 3
#micro http://localhost:8080/test.php?id=3%20or%201=1 PHP version:5.5.30
SQL is:select nickname from user where id = 3 or 1=1
#abc
#micro
#helloworld
#你好

加上转码:

$input_id = $pdo->quote($_GET['id']);

测试:

http://localhost:8080/test.php?id=3

PHP version:5.5.30
SQL is:select nickname from user where id = '3'
#micro http://localhost:8080/test.php?id=3%20or%201=1 PHP version:5.5.30
SQL is:select nickname from user where id = '3 or 1=1'
#micro

注意,pdo的quote自动加了引号,解决了这个问题。

http://localhost:8080/test.php?id=3%27%20or%201=%271

PHP version:5.5.30
SQL is:select nickname from user where id = '3\' or 1=\'1'
#micro

并且,尝试自己加引号去做侵入也没有用的。引号被转码了,所以成功防住攻击。

PDO的prepared statement:

<?php
header('Content-Type: text/html; charset=utf-8');
echo "PHP version:" . PHP_VERSION . "<br/>"; $pdo = new PDO("mysql:host=10.117.146.21:8306;dbname=springdemo", 'root', '[password]'); $prepared = $pdo->prepare('select nickname from user where id = :id'); $prepared->execute(array(':id' => $_GET['id'])); while ($results = $prepared->fetch(PDO::FETCH_ASSOC)) {
print_r($results['nickname'] . '<br/>');
} $pdo=null;
?>

实验:

http://localhost:8080/test.php?id=3

PHP version:5.5.30
micro http://localhost:8080/test.php?id=3%20or%201=1 PHP version:5.5.30
micro

都不再出现sql注入的威胁。

PDO里面多次用到fetch:

说明
PDO::FETCH_ASSOC 关联数组形式。
PDO::FETCH_NUM 数字索引数组形式。
PDO::FETCH_BOTH 两者数组形式都有,这是默认的。
PDO::FETCH_OBJ 按照对象的形式,类似于以前的mysql_fetch_object()函数。
PDO::FETCH_BOUND 以布尔值的形式返回结果,同时将获取的列值赋给bindParam()方法中指定的变量。
PDO::FETCH_LAZY 以关联数组、数字索引数组和对象3种形式返回结果。

把上面程序给prepared statement传参数的过程改了一下:

<?php
header('Content-Type: text/html; charset=utf-8');
echo "PHP version:" . PHP_VERSION . "<br/>"; $pdo = new PDO("mysql:host=10.117.146.21:8306;dbname=springdemo", 'root', '[password]'); $prepared = $pdo->prepare('select nickname from user where id = :id'); $prepared->bindParam(':id', $_GET['id']);
$prepared->execute(); while ($results = $prepared->fetch(PDO::FETCH_ASSOC)) {
print_r($results['nickname'] . '<br/>');
} $pdo=null;
?>

实验之后,结果对于上面哪些url,都能得到正确的结果。

性能方面:

PDO和MySQLi都有非常好的性能。在非prepared statements的基准测试下,MySQLi略快2.5%,而prepared statements下是6.5%,可以说对于性能无关紧要。
如果你真的非常介意这一点点性能的话,而自带的MySQL扩展比两者都快,你可以考虑下它。

上面部分来自这篇:http://blog.csdn.net/yipiankongbai/article/details/17277477 《PDO vs. MySQLi 选择哪一个?》

PDO(PHP Data Object),Mysqli,以及对sql注入等问题的解决的更多相关文章

  1. PDO(PHP Data Object)数据访问抽象层

    1.可以访问其它数据库2.具有事务功能3.带有预处理语句功能(防止SQL注入攻击) 访问数据库 PDO::__construct ( string $dsn [, string $username [ ...

  2. Java学习笔记47(JDBC、SQL注入攻击原理以及解决)

    JDBC:java的数据库连接 JDBC本质是一套API,由开发公司定义的类和接口 这里使用mysql驱动,是一套类库,实现了接口 驱动程序类库,实现接口重写方法,由驱动程序操作数据库 JDBC操作步 ...

  3. 关于SQL注入的问题以及解决方法

    1.关于SQL注入 什么是SQL注入: 由于jdbc程序在执行的过程中sql语句在拼装时使用了由页面传入参数,如果用户恶意传入一些sql中的特殊关键字,会导致sql语句意义发生变化,这种攻击方式就叫做 ...

  4. SQL注入实验,PHP连接数据库,Mysql查看binlog,PreparedStatement,mysqli, PDO

    看到有人说了判断能否sql注入的方法: 简单的在参数后边加一个单引号,就可以快速判断是否可以进行SQL注入,这个百试百灵,如果有漏洞的话,一般会报错. 下面内容参考了这两篇文章 http://blog ...

  5. PDO 学习与使用 ( 一 ) :PDO 对象、exec 方法、query 方法与防 SQL 注入

    1.安装 PDO 数据库抽象层 PDO - PHP Data Object 扩展类库为 PHP 访问数据库定义了一个轻量级的.一致性的接口,它提供了一个数据访问抽象层,针对不同的数据库服务器使用特定的 ...

  6. 如何使用PDO查询Mysql来避免SQL注入风险?ThinkPHP 3.1中的SQL注入漏洞分析!

    当我们使用传统的 mysql_connect .mysql_query方法来连接查询数据库时,如果过滤不严,就有SQL注入风险,导致网站被攻击,失去控制.虽然可以用mysql_real_escape_ ...

  7. SQL注入之代码层防御

    [目录] 0x0 前言 0x1 领域驱动的安全 1.1 领域驱动的设计 1.2 领域驱动的安全示例 0x2 使用参数化查询 2.1 参数化查询 2.2 Java中的参数化语句 2.3 .NET(C#) ...

  8. sql注入实例分析

    什么是SQL注入攻击?引用百度百科的解释: sql注入_百度百科: 所谓SQL注入,就是通过把SQL命令插入到Web表单提交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令.具 ...

  9. jdbc操作数据库以及防止sql注入

    public class pr { public static void main(String[] args) { Connection conn = null; Statement st = nu ...

随机推荐

  1. Oracle NULL 和空值

      如果你工作中用到了Oracle,你必须要留意NULL和空值的处理与SQL Server上的不同.现在让我们看些例子. 建立这张数据库表并插入记录 CREATE TABLE TestNull(Col ...

  2. topcoder 643 DIV2

    太弱了,太弱了! A:基本的判断吧,然后就是边界问题,写了好久,结果发现时房间第二个交的.. B:真心跪了,还好想出来了,思路想的太慢太慢,结果交上去,落后太多,不过HACK时很多人挂了, 这也是DI ...

  3. CodeForces 321A

    A. Ciel and Robot time limit per test 1 second memory limit per test 256 megabytes input standard in ...

  4. POJ 2823

    Sliding Window Time Limit: 12000MS   Memory Limit: 65536K Total Submissions: 35941   Accepted: 10636 ...

  5. POJ 3130 How I Mathematician Wonder What You Are!(半平面交求多边形的核)

    题目链接 题意 : 给你一个多边形,问你该多边形中是否存在一个点使得该点与该多边形任意一点的连线都在多边形之内. 思路 : 与3335一样,不过要注意方向变化一下. #include <stdi ...

  6. Axis学习的第一天

    下载axis的相关工程包: 选中这2个文件下载: 1)axis-bin-1.4.zip 含有axis工程包,将工程包复制到tomcat里的webapps目录下: 2)axis-src-1.4.zip ...

  7. yum downloadonly

         有些时候集群中的机器无法联网,通过yum进行安装,这样就需要找一个相同内核的机器将rpm下载后再到相应的机器上进行安装,以解决这一问题.      yum 有相应的工具完成这一任务.     ...

  8. 多项式求ln,求exp,开方,快速幂 学习总结

    按理说Po姐姐三月份来讲课的时候我就应该学了 但是当时觉得比较难加上自己比较懒,所以就QAQ了 现在不得不重新弄一遍了 首先说多项式求ln 设G(x)=lnF(x) 我们两边求导可以得到G'(x)=F ...

  9. C语言标准

    1,K&R C 1978年, Dennis Ritchie和Brian Wilson Kernighan合作出版了<The C Programming Language>的第一版. ...

  10. 超级内存NVDIMM

    1.序言 基于非易失性内存(NVDIMM)的新一代内存条规格已经研制成功,其中集成了DRAM和非易失性存储芯片,能够在完全断电的时候完整保存内存数据,并支持主内存在持久高速高性能计算上的应用.区别于普 ...