PHP防止sql语句注入终极解决方案(包含pdo各种操作使用实例)
PHP防止sql语句注入终极解决方案
完美解决方案就是使用拥有Prepared Statement机制(预处理sql)的PDO
//先做个实验 先不用预处理sql写法
<pre>
<?php
$pdo = new PDO('mysql:dbname=testdatabase;host=localhost;charset=utf8', 'root', 'root');
$id='2 or 1=1';
$stmt=$pdo->query('SELECT * FROM wz_admin WHERE id = '.$id);
print_r($stmt -> fetchAll ());
exit();
可以发现 可以输出数据 id=2的时候是没数据的
?>
</pre>
用预处理sql写法
$dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
它会告诉 PDO 禁用模拟预处理语句,并使用 real parepared statements 。这可以确保SQL语句和相应的值在传递到mysql服务器之前是不会被PHP解析的(禁止了所有可能的恶意SQL注入攻击)。
<pre>
$pdo = new PDO('mysql:dbname=testdatabase;host=localhost;charset=utf8', 'root', 'root');
$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$stmt = $pdo->prepare('SELECT * FROM wz_admin WHERE id = :id');
$id='2 or 1=1';
$stmt->execute(array('id' => $id));
print_r($stmt -> fetchAll ());
exit();
</pre>
可以发现没有输出数据
<pre>
上面这段代码就可以防范sql注入。为什么呢?
当调用 prepare() 时,查询语句已经发送给了数据库服务器,此时只有占位符 ? 发送过去,没有用户提交的数据;当调用到 execute()时,用户提交过来的值才会传送给数据库,它们是分开传送的,两者独立的,SQL攻击者没有一点机会
<?php
下面我简单的封装了下
class Db
{
private static $pdo;
public static function getPdo ()
{
if ( self::$pdo == null )
{
$host = 'localhost';
$user = 'root';
$pwd = '';
$dbname = 'testdatebase';
$dsn = "mysql:host=$host;dbname=$dbname;port=3306";
$pdo = new PDO ( $dsn, $user, $pwd );
$pdo->query('set names utf8;');
$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
self::$pdo = $pdo;
}
return self::$pdo;
}
public static function getStmt($sql)
{
$pdo = self::getPdo();
return $pdo->prepare($sql);
}
public static function getinsertids()
{
$pdo = self::getPdo();
$insertid = $pdo->lastInsertId();
return $insertid;
}
public static function SETATTR_AUTOCOMMIT()
{
$pdo = self::getPdo();
$pdo->setAttribute(PDO::ATTR_AUTOCOMMIT, 0);
}
public static function beginTransactions()
{
$pdo = self::getPdo();
$pdo->beginTransaction();//开启事务处理
}
public static function commits()
{
$pdo = self::getPdo();
$pdo->commit();//开启事务处理
}
public static function roolbacks()
{
$pdo = self::getPdo();
$pdo->rollBack();//开启事务处理
}
}
$sql = "SELECT * FROM wz_admin WHERE id = ?";
$stmt = Db::getStmt ( $sql );
$stmt -> execute ( array (1));
//PDO::FETCH_ASSOC这个参数代表只显示关联数组 默认是显示索引下标和关联数组的
print_r($stmt -> fetchAll (PDO::FETCH_ASSOC));
exit();
//以下返回1 都是数据库操作成功的
$sql = "INSERT INTO testss (wef,wef1) VALUES(?,?)";
$stmt = Db::getStmt ( $sql );
$dd=$stmt -> execute ( array ('wefe','wefe1'));
print_r($dd);
exit();
$sql = "update testss set wef=? where id=2";
$stmt = Db::getStmt ( $sql );
$dd=$stmt -> execute ( array ('34'));
print_r($dd);
//事务 只有commit得而时候才会执行sql语句 如果过程中报错就会roolbacks 返回到初始状态
/*DB::SETATTR_AUTOCOMMIT();
$username=$_POST['username'];
$sql = 'INSERT INTO arjianghu_register (username) VALUES(?)';
$stmt = \Db::getStmt($sql);
Db::beginTransactions();//开启事务处理
$isOk = $stmt->execute(array($username));
if(!$isOk){
Db::roolbacks();
echo json_encode(array('success'=>0,'msg'=>'网络繁忙','data'=>''));
exit();
}
$sql = 'INSERT INTO arjianghu_zhuangtai (personid) VALUES(?)';
$stmt = \Db::getStmt($sql);
$isOk = $stmt->execute(array(1));
if($isOk){
echo json_encode(array('success'=>1,'msg'=>'操作成功','data'=>''));
exit();
}else{
Db::roolbacks();
echo json_encode(array('success'=>0,'msg'=>'网络繁忙','data'=>''));
exit();
}
DB::commits();*/
?>
</pre>
ps:之所以预处理sql 能够防止注入式因为 他内部经过了转义等其他处理
ps:pdo字段不能用?必须要变量 ?只能用在值
PHP防止sql语句注入终极解决方案(包含pdo各种操作使用实例)的更多相关文章
- SQL语句查询时防止SQL语句注入的方法之一
1.传参时有可能出现SQL语句注入 StringBuffer sb = new StringBuffer(); if(StringUtils.isNotBlank(areaCode)) { sb.ap ...
- sql server的sql 语句中的列名包含[]时候,把]替换成]]就可以
sql server的sql 语句中的列名包含[]时候,把]替换成]]就可以eg: create table p.e_LOG_WebServer ( [BSCFlg] int, ), ) ); sel ...
- sql语句实现行转列的3种方法实例
sql语句实现行转列的3种方法实例 一般在做数据统计的时候会用到行转列,假如要统计学生的成绩,数据库里查询出来的会是这样的,但这并不能达到想要的效果,所以要在查询的时候做一下处理,下面话不多说了,来一 ...
- 登录测试用例sql语句注入
利用SQL注入漏洞登录后台的实现方法 作者: 字体:[增加 减小] 类型:转载 时间:2012-01-12我要评论 工作需要,得好好补习下关于WEB安全方面的相关知识,故撰此文,权当总结,别无它意.读 ...
- 跨服务器导入数据SQL语句及其问题解决方案
--跨服务器导入数据SQL语句: insert into [shsw_manager].[dbo].[Station_List]select * from OPENROWSET('SQLOLEDB', ...
- sql无效字符 执行sql语句报错解决方案
以为是sql中参数赋值有问题,但是将sql语句直接copy到PLSQL中执行,却没问题,纠结了好久,原来是 insert语句多了:唉,坑爹 http://www.jb51.net/article/32 ...
- SQL语句汇总(一)——数据库与表的操作以及创建约束
首先,非常感谢大家对上篇博文的支持,真是让本菜受宠若惊,同时对拖了这么久才出了此篇表示抱歉. 前言:此文旨在汇总从建立数据库到联接查询等绝大部分SQL语句.SQL语句虽不能说很多,但稍有时间不写就容易 ...
- SQL语句注入
1: select *from user where username='admin' and password='123456' or 1='1'; 万能密码 2: ...
- 数据库的SQL语句创建和主外键删除操作
create table UserType ( Id ,), Name nvarchar() not null ) go create table UserInfo ( Id ,), LoginPwd ...
随机推荐
- Async/await promise实现
An async function can contain an await expression that pauses the execution of the async function an ...
- react hooks沉思录
将UI组件抽象为状态处理机.分为普通状态和副作用状态. 一.综述 useState:处理函数只改变引用的状态本身:副作用状态:会对引用状态以外的状态和变量进行修改:useReducer:用解藕化的机制 ...
- micronaut 学习一 基本安装
一般来说,使用框架就是使用类库同时按照框架的类库套路编写代码,但是从越来越复杂的实际 场景来说,cli以及脚手架工具,可以帮助我们简化好多操作. 以下是micronaut cli 工具的安装以及一个简 ...
- 【LG3783】[SDOI2017]天才黑客
[LG3783][SDOI2017]天才黑客 题面 洛谷 题解 首先我们有一个非常显然的\(O(m^2)\)算法,就是将每条边看成点, 然后将每个点的所有入边和出边暴力连边跑最短路,我们想办法优化这里 ...
- JVM参数笔记
Java启动参数共分为三类: 其一是标准参数(-),所有的JVM实现都必须实现这些参数的功能,而且向后兼容: 其二是非标准参数(-X),默认jvm实现这些参数的功能,但是并不保证所有jvm实现都满足, ...
- tomcat做成Windows自启动服务
一.下载Tomcat 下载Windows版本的tomcat,一般是以zip结尾的包,免安装的包,而Linux包虽然解压可以运行,但是缺少service.bat关键文件,无法做成服务形式 下载网站: h ...
- ln -s 使用
最近开发项目中遇到一个问题,网站上传文件到项目根目录下的upload文件夹,但是每次项目发布都会把upload文件夹删除掉,所以我们需要把upload文件夹放在系统目录下而不是项目根目录下. 访问的时 ...
- 经典算法(三) 单链表 反转 & 是否相交/成环 & 求交点 等
参考文章: 判断链表是否相交:http://treemanfm.iteye.com/blog/2044196 一.单链表反转 链表节点 public class Node { private int ...
- JavaScript的filter方法
var ages = [32, 33, 16, 40]; function checkAdult(age) { return age >= 18; } function myFunction() ...
- SVN提示is already locked 解决办法
当svn提示is already locked ,反复clean up也无用, 可以在cmd下进入到目标文件夹的目录 执行svn cleanup 等待执行成功,就可以update了