安全的方式:
$pdo = new PDO('mysql:host=localhost;dbname=phptry','username','passwd');
$pdo->query("SET NAMES 'utf8'");//字符集设置
//$pdo->query("SET character_set_client=binary");?
//设置不在本地做sql语句预处理,php5.3.6之后默认
//$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
//修改默认的错误显示级别
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
//sql预处理和执行------------------------
$statement = $pdo->prepare("select * from user where username = ?");
$statement->bindValue(1,'admin',PDO::PARAM_STR);//bindvalue绑定":XXX"或者用替代第几个问号,bindparam只能绑定变量
$statement->execute();
//处理返回的结果集----------------------------
//取不到则返回false
$row = $statement->fetch(PDO::FETCH_ASSOC);
//取不到则返回空数组
//$row = $statement->fetchAll(PDO::FETCH_OBJ);
//debug模式下查看预处理语句参数,要在execute()方法后调用
//$statement->debugDumpParams();
//查看结果
echo htmlentities(count($row)); //count()/sizeof()
var_dump($row); //输出参数类型和值
或者写成:
$pdo = new PDO('mysql:host=localhost;dbname=phptry;charset=utf8','username','passwd');
//修改默认的错误显示级别
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
//sql预处理和执行------------------------
$statement = $pdo->prepare("select * from user where username = ?");
$statement->bindValue(1,'admin',PDO::PARAM_STR);
$statement->execute(array("admin"));//传递数组参数
//省略----------------------------
bindValue和bindParam会对特殊符号进行转义。
$statement->debugDumpParams();结果显示:
SQL: [37] select * from user where username = ?
Params: 1
Key: Position #0:
paramno=0
name=[0] ""
is_param=1
param_type=2
Array
防sql注入原理:
在php5.3.6之后,pdo不会在本地对sql进行拼接然后将拼接后的sql传递给mysql server处理(也就是不会在本地做转义处理)。pdo的处理方法是在prepare函数调用时,将预处理好的sql模板(包含占位符)通过mysql协议传递给mysql server,告诉mysql server模板的结构以及语义。当调用execute时,将两个参数传递给mysql server。由mysql server完成变量的转移处理。将sql模板和变量分两次传递,即解决了sql注入问题。
sql注入测试:
$statement = $pdo->prepare("select * from user where username = ?");
$statement->execute(array("'' or 1 > 0"));
$row = $statement->fetchAll(PDO::FETCH_OBJ);
var_dump($row);
//输出array(0) { } ,成功
参考链接: