zoukankan      html  css  js  c++  java
  • 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字段不能用?必须要变量 ?只能用在值

  • 相关阅读:
    ORA55610: Invalid DDL statement on historytracked table
    EXP00008: ORACLE error 1455 encountered
    [bbk5138] 第48集 第五章 管理内存 03
    [bbk5130] 第46集 第五章 管理内存 01
    Oracle11g新特性:Flashback Data Archive续
    [bbk5120] 第44集 第四章 Flashback Database 08
    欧拉计划第十一题java实现
    C迷途指针
    梯度vs Jacobian矩阵vs Hessian矩阵
    支持向量机(SVM)必备概念(凸集和凸函数,凸优化问题,软间隔,核函数,拉格朗日乘子法,对偶问题,slater条件、KKT条件)
  • 原文地址:https://www.cnblogs.com/newmiracle/p/11872518.html
Copyright © 2011-2022 走看看