SQL预处理语句的使用及防注入

许多成熟的数据库都支持预处理语句(Prepared Statements)的概念。它们是什么东西?php

你能够把它们想成是一种编译过的要执行的SQL语句模板,可使用不一样的变量参数定制它。数据库

预处理语句具备两个主要的优势:框架

  • 查询只须要被解析(或准备)一次,但可使用相同或不一样的参数执行屡次。
    • 当查询准备好(Prepared)以后,数据库就会分析,编译并优化它要执行查询的计划。
    • 对于复杂查询来讲,若是你要重复执行许屡次有不一样参数的但结构相同的查询,这个过程会占用大量的时间,使得你的应用变慢。
    • 经过使用一个预处理语句你就能够避免重复分析、编译、优化的环节。
    • 简单来讲,预处理语句使用更少的资源,执行速度也就更快。
  • 传给预处理语句的参数不须要使用引号,底层驱动会为你处理这个。
    • 若是你的应用独占地使用预处理语句,你就能够确信没有SQL注入会发生。
    • 然而,若是你仍然在用基于不受信任的输入来构建查询的其余部分,这仍然是具备风险的

正由于预处理语句是如此有用,它成了PDO惟一为不支持此特性的数据库提供的模拟实现。fetch

这使你可使用统一的数据访问规范而没必要关心数据库自己是否具有此特性。优化

/*
使用预处理语句重复插入数据(1)
此示例演示了一个经过向命名占位符代入一个name和一个value值来执行的INSERT查询
*/
$stmt= $dbh->prepare("INSERT INTO REGISTRY (name, value) VALUES (:name, :value)");
$stmt->bindParam(':name', $name);
$stmt->bindParam(':value', $value); //插入一行
$name= 'one';
$value= 1;
$stmt->execute();//使用不一样的值插入另外一行
$name= 'two';
$value= 2;
$stmt->execute();

/*
使用预处理语句重复插入数据(2)
此示例演示了一个经过向用?表示的占位符代入一个name和一个value值来执行的INSERT查询
*/
$stmt= $dbh->prepare("INSERT INTO REGISTRY (name, value) VALUES (?, ?)");
$stmt->bindParam(1, $name);
$stmt->bindParam(2, $value); // 插入一行
$name= 'one';
$value= 1;
$stmt->execute(); // 使用不一样的值插入另外一行
$name= 'two';
$value= 2;
$stmt->execute();

/*
经过预处理语句获取数据
此示例演示使用从表单获取的数据为关键值来执行查询获取数据。用户的输入会被自动添加引号,因此这儿不存在SQL注入攻击的危险。
*/
$stmt= $dbh->prepare("SELECT * FROM REGISTRY where name = ?");
    if($stmt->execute(array($_GET['name']))) {
        while($row= $stmt->fetch()) {
        print_r($row);
    }
}

其实主流的PHP框架都支持Prepared Statements,并且要简单不少。下面是ThinkPHP模型支持的例子:.net

// 实例化User模型
$model= D('User');

// 定义预处理传入数据
$data['username'] = 'deeka';
$data['password'] = '123456';

// 数据预处理
if($model->create($data)){
    $model->add();
}

参考资料

相关文章
相关标签/搜索