PDO(PHP Data Object),Mysqli,以及对sql注入等问题的解决
这篇是上一篇 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注入等问题的解决的更多相关文章
- PDO(PHP Data Object)数据访问抽象层
1.可以访问其它数据库2.具有事务功能3.带有预处理语句功能(防止SQL注入攻击) 访问数据库 PDO::__construct ( string $dsn [, string $username [ ...
- Java学习笔记47(JDBC、SQL注入攻击原理以及解决)
JDBC:java的数据库连接 JDBC本质是一套API,由开发公司定义的类和接口 这里使用mysql驱动,是一套类库,实现了接口 驱动程序类库,实现接口重写方法,由驱动程序操作数据库 JDBC操作步 ...
- 关于SQL注入的问题以及解决方法
1.关于SQL注入 什么是SQL注入: 由于jdbc程序在执行的过程中sql语句在拼装时使用了由页面传入参数,如果用户恶意传入一些sql中的特殊关键字,会导致sql语句意义发生变化,这种攻击方式就叫做 ...
- SQL注入实验,PHP连接数据库,Mysql查看binlog,PreparedStatement,mysqli, PDO
看到有人说了判断能否sql注入的方法: 简单的在参数后边加一个单引号,就可以快速判断是否可以进行SQL注入,这个百试百灵,如果有漏洞的话,一般会报错. 下面内容参考了这两篇文章 http://blog ...
- PDO 学习与使用 ( 一 ) :PDO 对象、exec 方法、query 方法与防 SQL 注入
1.安装 PDO 数据库抽象层 PDO - PHP Data Object 扩展类库为 PHP 访问数据库定义了一个轻量级的.一致性的接口,它提供了一个数据访问抽象层,针对不同的数据库服务器使用特定的 ...
- 如何使用PDO查询Mysql来避免SQL注入风险?ThinkPHP 3.1中的SQL注入漏洞分析!
当我们使用传统的 mysql_connect .mysql_query方法来连接查询数据库时,如果过滤不严,就有SQL注入风险,导致网站被攻击,失去控制.虽然可以用mysql_real_escape_ ...
- SQL注入之代码层防御
[目录] 0x0 前言 0x1 领域驱动的安全 1.1 领域驱动的设计 1.2 领域驱动的安全示例 0x2 使用参数化查询 2.1 参数化查询 2.2 Java中的参数化语句 2.3 .NET(C#) ...
- sql注入实例分析
什么是SQL注入攻击?引用百度百科的解释: sql注入_百度百科: 所谓SQL注入,就是通过把SQL命令插入到Web表单提交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令.具 ...
- jdbc操作数据库以及防止sql注入
public class pr { public static void main(String[] args) { Connection conn = null; Statement st = nu ...
随机推荐
- Oracle 显示时间问题
在部署的时候. 显示的时间为会 2014/1/1 9:00:00 pm 但开发过程中显示为正常: 2014-1-1 21:00:00 解决方法: 1. Oracle数据库的时间格式没有问题, ...
- Unity3D开发Windows Store应用程序 注意事项
原地址:http://blog.csdn.net/jbjwpzyl3611421/article/details/12704491 针对最近在移植window store项目中遇到的问题,我整理了官方 ...
- 在Delphi中实现动画窗口
Windows下有一个函数AnimateWindow,在Delphi自带的Win32 API Help中是找不到的.你可以在Delphi的编辑器中输入windows.等待代码向导出来,继续输入Anim ...
- UITableView多选删除
设置一个在编辑状态下点击可改变图片的cell FileItemTableCell.h #import <UIKit/UIKit.h> @interface FileItemTableCel ...
- isMobile 一个简单的JS库,用来检测移动设备
点这里 github地址:https://github.com/kaimallea/isMobile Example Usage I include the minified version of t ...
- POJ 3150 Cellular Automaton(矩阵乘法+二分)
题目链接 题意 : 给出n个数形成环形,一次转化就是将每一个数前后的d个数字的和对m取余,然后作为这个数,问进行k次转化后,数组变成什么. 思路 :下述来自here 首先来看一下Sample里的第一组 ...
- 由CAST()函数在.NET1.1和.NET4.0下处理机制不同所引发的BUG
.NET 1.1版本下使用日期强制转换函数,比如:"select cast(ActionDate as char(7)) as ActionDate from ST_BookAction ...
- SPRING IN ACTION 第4版笔记-第十章Hitting the database with spring and jdbc-001-Spring对原始JDBC的封装
1.spring扩展的jdbc异常 2.Template的运行机制 Spring separates the fixed and variable parts of the data-access p ...
- 295. Find Median from Data Stream
题目: Median is the middle value in an ordered integer list. If the size of the list is even, there is ...
- Centos下修改启动项和网络配置
1.Centos默认是从图形界面启动,需要较多的资源,为了节省资源可以从命令行启动.修改方法如下: /etc/inittab文件,把 代码: id:5:initdefault:这一行,修改成 代码: ...