PHP防止sql语句注入终极解决方案(包含pdo各种操作使用实例)详解编程语言
PHP防止sql语句注入终极解决方案
完美解决方案就是使用拥有Prepared Statement机制(预处理sql)的PDO
//先做个实验 先不用预处理sql写法
?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的时候是没数据的
?
用预处理sql写法
$dbh- setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
它会告诉 PDO 禁用模拟预处理语句,并使用 real parepared statements 。这可以确保SQL语句和相应的值在传递到mysql服务器之前是不会被PHP解析的(禁止了所有可能的恶意SQL注入攻击)。
$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();
可以发现没有输出数据
上面这段代码就可以防范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();*/
?
ps:之所以预处理sql 能够防止注入式因为 他内部经过了转义等其他处理
ps:pdo字段不能用?必须要变量 ?只能用在值
19060.html
cjavamysqlphp相关文章
- solid原则应用实例_设计模式solid原则
- SQL Server解析/操作Json格式字段数据的方法实例
- 使用PHP操作Redis实例:简单高效的数据存储方案(php操作redis实例)
- MacOS上配置PHP环境的指南(Macos配置php)
- 使用PHP实现Redis分布式缓存(php实例化redis)
- PHP技术防止MSSQL注入风险(php防止mssql注入)
- PHP解决MSSQL数据库乱码问题(php解决mssql乱码)
- 从头到尾:使用PHP进行MSSQL手工注入(php手工注入mssql)
- PHP如何访问MS SQL服务器(php怎么访问mssql)
- PHP暂不支持MSSQL数据库的连接(php不支持mssql)
- Linux 下学习 PHP 开发入门(linux下开发php)
- Linux下查看 PHP 进程信息(linux查看php进程)
- 实例研究Oracle事务处理机制(oracle事务示例)
- PHP翻页实例代码
- php下把数组保存为文件格式的实例应用
- javascript实现TreeView无刷新展开的实例代码
- php使用异或实现的加密解密实例
- php初始化对象和析构函数的简单实例
- 简单实用的PHP防注入类实例
- PHP和javascript常用正则表达式及用法实例
- php调用mysql存储过程实例分析
- 基于C语言实现五子棋游戏完整实例代码
- php+xml编程之xpath的应用实例
- PHP邮件发送类PHPMailer用法实例详解
- php密码生成类实例