【php】PDO資料庫防sql注入
阿新 • • 發佈:2019-01-01
安全的方式:
$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) { } ,成功
參考連結: