⑴ php 關於thinkphp的防sql注入跟過濾問題
防止注入
opensns
對於WEB應用來說,SQL注入攻擊無疑是首要防範的安全問題,系統底層對於數據安全方面本身進行了很多的處理和相應的防範機制,例如:
$User = M("User"); // 實例化User對象
$User->find($_GET["id"]);
即便用戶輸入了一些惡意的id參數,系統也會強制轉換成整型,避免惡意注入。這是因為,系統會對數據進行強制的數據類型檢測,並且對數據來源進行數據格式轉換。而且,對於字元串類型的數據,ThinkPHP都會進行escape_string處理(real_escape_string,mysql_escape_string)。
通常的安全隱患在於你的查詢條件使用了字元串參數,然後其中一些變數又依賴由客戶端的用戶輸入,要有效的防止SQL注入問題,我們建議:
查詢條件盡量使用數組方式,這是更為安全的方式;
如果不得已必須使用字元串查詢條件,使用預處理機制(3.1版本新增特性);
開啟數據欄位類型驗證,可以對數值數據類型做強制轉換;(3.1版本開始已經強制進行欄位類型驗證了)
使用自動驗證和自動完成機制進行針對應用的自定義過濾;
欄位類型檢查、自動驗證和自動完成機制我們在相關部分已經有詳細的描述。
查詢條件預處理
where方法使用字元串條件的時候,支持預處理(安全過濾),並支持兩種方式傳入預處理參數,例如:
$Model->where("id=%d and username='%s' and xx='%f'",array($id,$username,$xx))->select();
或者
$Model->where("id=%d and username='%s' and xx='%f'",$id,$username,$xx)->select();
模型的query和execute方法 同樣支持預處理機制,例如:
$model->query('select * from user where id=%d and status=%d',$id,$status);
或者
$model->query('select * from user where id=%d and status=%d',array($id,$status));
execute方法用法同query方法。
⑵ php sql 過濾重復
只需要在給sql語句中加個DISTINCT , sql 語句distinct的用法為SELECT DISTINCT 列名稱 FROM 表名稱 ,即 $sql="select distinct CD_Singer from ".tname('dj')."";
⑶ php如何避免在循環中使用sql語句
1、循環內拼接sql語句,循環外執行
例如:
//假設這里的$users是一個很大的數組,我們要循環取出其中的值foreach($users as $user){//這部分的sql是我從項目中隨便摘抄出來的。主要就是實現拼接sql語句$sql .= " ('{$order_sn}', '{$this->user_id}', '{$deliver_fee}', 0, "
. " '', '', '', "
. " '{$add_time}','{$order_status}', '{$order_amount}', '{$remark}', "
. " '{$pickup_code}', '{$self_pickup}', '{$collect_order_sn}', '{$key}', {$reservation_time}),";
}
//循環中拼接好sql之後,我們在循環外執行$sql = substr($sql, 0, -1);
DB::statement($sql);1234567891011
2、where條件換為where in()
比如我們的where()條件中要使用大規模的數組,那麼在語句應該是:
foreach($arr as $v){
DB::table('')->where('id',$v->id);
}123
此時我們可以轉變一下:
//先取出條件數組$arr,在直接執行whereIn即可DB::table('')->whereIn('id',$arr);12
注意:如果數據量很大,比如幾十萬條數據,那麼whereIn也會成為代碼的瓶頸,這個函數適用於數據量不是很大的情況。
⑷ PHP如何去執行一個SQL語句
<?php
$db_server="localhost";
$db_user="root";
$db_pwd="password";
$db_name="test";
$sql="select*fromuserwhereusername='admin'";
$conn=mysql_pconnect($db_server,$db_user,$db_pwd);
$my_db=mysql_select_db($db_name,$conn);
$result=mysql_query($sql,$conn);
$userInfo=mysql_fetch_array($result);
mysql_close($conn);
echo"帳戶:".$userInfo["username"]."";
echo"密碼:".$userInfo["password"]."";
echo"年齡:".$userInfo["userage"]."";
echo"等級:".$userInfo["usergrade"]."";
?>
⑸ [php]防sql語句注入函數,怎麼使用
在你的代碼里
$sql = ....
if (!inject_chk($sql))
{
//執行...
}
else
{
echo "有注入危險";
}
⑹ php怎樣過濾非法字元防止sql注入
htmlspecialchars($_POST['欄位']),用這個函數就可以將一些特殊字元進行過濾轉義。你可以去看看這個函數的說明。
⑺ php怎麼獲取上一條執行的sql語句
首先明確一點,PHP和MySQL原生是不支持獲取上一條查詢語句的。各大框架都是封裝函數來實現的。這里以CI框架來說明,其他框架原理都大同小異。
設置成員變數,用於存儲執行過的sql語句。
思路具體就是如此,具體邏輯根據需求可以自由調整。
⑻ 求php防止被sql 注入攻擊的過濾用戶輸入內容的函數
functionclean($v){
//判斷magic_quotes_gpc是否為打開
if(!get_magic_quotes_gpc()){
//進行magic_quotes_gpc沒有打開的情況對提交數據的過濾
$v=addslashes($v);
}
//把'_'過濾掉回
$v=str_replace("_","\_",$v);
//把'%'過濾掉
$v=str_replace("%","\%",$v);
//把'*'過濾掉
$v=str_replace("*","*",$v);
//回車轉換答
$v=nl2br($v);
//html標記轉換
$v=htmlspecialchars($v);
return$v;
}
如果需要,還可以屏蔽一下危險字元,例如insert, update, delete等
//將update去掉
$v=str_replace("update","",$v);
最後,在拼裝sql語句時,用戶輸入的東西,全括在單引號內
⑼ PHP中如何防止SQL注入
我把問題和贊同最多的答題翻譯了下來。提問:如果用戶的輸入能直接插入到SQL語句中,那麼這個應用就易收到SQL注入的攻擊,舉個例子:$unsafe_variable = $_POST['user_input']; mysqli_query("INSERT INTO table (column) VALUES ('" . $unsafe_variable . "')");用戶可以輸入諸如 : value'); DROP TABLE table;-- ,SQL語句就變成這樣了:INSERT INTO table (column) VALUES('value'); DROP TABLE table;--')(譯者註:這樣做的結果就是把table表給刪掉了) 我們可以做什麼去阻止這種情況呢?回答:使用prepared statements(預處理語句)和參數化的查詢。這些SQL語句被發送到資料庫伺服器,它的參數全都會被單獨解析。使用這種方式,攻擊者想注入惡意的SQL是不可能的。要實現這個主要有兩種方式:1. 使用 PDO:$stmt = $pdo->prepare('SELECT * FROM employees WHERE name = :name'); $stmt->execute(array(':name' => $name)); foreach ($stmt as $row) { // do something with $row }2. 使用 Mysqli:$stmt = $dbConnection->prepare('SELECT * FROM employees WHERE name = ?'); $stmt->bind_param('s', $name); $stmt->execute(); $result = $stmt->get_result(); while ($row = $result->fetch_assoc()) { // do something with $row }PDO需要注意的是使用PDO去訪問MySQL資料庫時,真正的prepared statements默認情況下是不使用的。為了解決這個問題,你需要禁用模擬的prepared statements。下面是使用PDO創建一個連接的例子:$dbConnection = new PDO('mysql:dbname=dbtest;host=127.0.0.1;charset=utf8', 'user', 'pass'); $dbConnection->setAttribute(PDO::ATTR_EMULATE_PREPARES, false); $dbConnection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);上面的例子中,錯誤報告模式並不是強制和必須的,但建議你還是添加它。通過這種方式,腳本在出問題的時候不會被一個致命錯誤終止,而是拋出PDO Exceptions,這就給了開發者機會去捕獲這個錯誤。然而第一行的 setAttribute() 是強制性的,它使得PDO禁用模擬的prepared statements並使用真正的prepared statements。這可以確保這些語句和值在被發送到MySQL伺服器之前不會被PHP解析(這使得攻擊者沒有注入惡意SQL的機會)。盡管你可以使用可選的構造函數參數去設置 charset ,但重點需要注意的是小於5.3.6的PHP版本,DSN(Data Source Name)是默認忽略 charset 參數的。說明當你傳一個SQL語句做預處理時會發生什麼?它被資料庫伺服器解析和編譯了。通過指定參數(通過之前例子中的 ? 或者像 :name 這樣的命名式參數)你告訴資料庫引擎你是想過濾它。接著當你調用 execute() 函數時,prepared statements會和你剛才指定的參數的值結合。在此重要的是,參數的值是和編譯過的語句結合,而非一個SQL字元串。SQL注入就是當創建被發送到資料庫的SQL語句時,通過欺騙的手段讓腳本去引入惡意的字元串。因此當你使用單獨的參數發送真實正確的SQL時,你就限制了被某些不是你真實意圖的事情而搞掛掉的風險。使用prepared statements 傳遞的任何參數都會被當做字元串對待(不過資料庫引擎可能會做一些優化,這些參數最終也可能變成numbers)(譯者註:意思就是把參數當做一個字元串而不會去做額外的行為)。比如在上面的例子中,如果 $name 變數的值是 'Sarah'; DELETE * FROM employees ,產生的結果是會去搜索"'Sarah'; DELETE * FROM employees"這一整個字元串,最終的結果你也就不會面對的是一張空表了。使用prepared statements的另一個好處是,如果你在同一session中再次執行相同的語句,也就不會被再次解析和編譯,這樣你就獲得一些速度上的提升。