首頁  >  文章  >  後端開發  >  PHP防止sql注入的方法解說

PHP防止sql注入的方法解說

韦小宝
韦小宝原創
2018-03-01 09:58:452173瀏覽

在我們的日常PHP開發網站中防止sql注入是最好要寫的一道程序,因為它可以給我們開發的網站起到保護的作用,相信很多PHP初級程式設計師都並沒有寫防止SQL注入的習慣,一部分可能是不會,那我們今天就來講講如何用PHP來實現防止sql的注入。

產生原因

一方面自己沒這方面的意識,有些資料沒有經過嚴格的驗證,然後直接拼接 SQL 去查詢。導致漏洞產生,例如:

$id  = $_GET['id'];
$sql = "SELECT name FROM users WHERE id = $id";

因為沒有對$_GET['id'] 做數據類型驗證,注入者可提交任何類型的數據,例如" and 1= 1 or " 等不安全的數據。如果按照下面方式寫,就安全一些。

$id  = intval($_GET['id']);
$sql = "SELECT name FROM users WHERE id = $id";

把 id 轉換成 int 型,就可以去掉不安全的東西。

驗證資料

防止注入的第一步是驗證數據,可以根據對應類型進行嚴格的驗證。例如 int 類型直接同過 intval 進行轉換就行:

$id =intval( $_GET['id']);

字元處理起來比較複雜些,先透過 sprintf 函數格式話輸出,確保它是一個字串。然後透過一些安全函數去掉一些不合法的字符,例如:

$str = addslashes(sprintf("%s",$str)); 
//也可以用 mysqli_real_escape_string 函数替代addslashes

這樣處理以後會比較安全。當然也可以進一步判斷字串長度,去防止「緩衝區溢位攻擊」例如:

$str = addslashes(sprintf("%s",$str));
$str = substr($str,0,40); 
//最大长度为40

參數化綁定

#參數化綁定,防止SQL 注入的另一道屏障。 php MySQLi 和 PDO 都提供這樣的功能。例如MySQLi 可以這樣去查詢:

$mysqli = new mysqli('localhost', 'my_user', 'my_password', 'world');
$stmt = $mysqli->prepare("INSERT INTO CountryLanguage VALUES (?, ?, ?, ?)");
$code = 'DEU';
$language = 'Bavarian';
$official = "F";
$percent = 11.2;
$stmt->bind_param('sssd', $code, $language, $official, $percent);

PDO 的更是方便,例如:

/* Execute a prepared statement by passing an array of values */
$sql = 'SELECT name, colour, calories
    FROM fruit
    WHERE calories < :calories AND colour = :colour&#39;; $sth = $dbh->prepare($sql, array(PDO::ATTR_CURSOR => PDO::CURSOR_FWDONLY));
$sth->execute(array(&#39;:calories&#39; => 150, &#39;:colour&#39; => &#39;red&#39;));
$red = $sth->fetchAll();
$sth->execute(array(&#39;:calories&#39; => 175, &#39;:colour&#39; => &#39;yellow&#39;));
$yellow = $sth->fetchAll();

我們多數使用php 的框架進行編程,所以最好不要自己拼字SQL,依照框架給定參數綁定進行查詢。遇到較複雜的 SQL 語句,一定要自己拼字的時候,一定要注意嚴格的判斷。沒有用 PDO 或 MySQLi 也可以自己寫 prepared,像是 wordprss db 查詢語句,可以看出也是經過嚴格的型別驗證。

function prepare( $query, $args ) {
    if ( is_null( $query ) )
         return;
    // This is not meant to be foolproof -- 
           but it will catch obviously incorrect usage.
    if ( strpos( $query, &#39;%&#39; ) === false ) {
         _doing_it_wrong( &#39;wpdb::prepare&#39; , 
         sprintf ( ( &#39;The query argument of %s
                 must have a placeholder.&#39; ), &#39;wpdb::prepare()&#39; ), &#39;3.9&#39; );
   }
    $args = func_get_args();
    array_shift( $args );
    // If args were passed as an array (as in vsprintf), move them up
    if ( isset( $args[ 0] ) && is_array( $args[0]) )
         $args = $args [0];
    $query = str_replace( "&#39;%s&#39;", &#39;%s&#39; , $query ); 
        // in case someone mistakenly already singlequoted it
    $query = str_replace( &#39;"%s"&#39;, &#39;%s&#39; , $query ); 
        // doublequote unquoting
    $query = preg_replace( &#39;|(?<!%)%f|&#39; , &#39;%F&#39; , $query ); 
        // Force floats to be locale unaware
    $query = preg_replace( &#39;|(?<!%)%s|&#39;, "&#39;%s&#39;" , $query ); 
        // quote the strings, avoiding escaped strings like %%s
    array_walk( $args, array( $this, &#39;escape_by_ref&#39; ) );
    return @ vsprintf( $query, $args );
}

總結

安全性很重要,也可以看出一個人基本功,專案漏洞百出,擴展性和可維護性再好也沒用。平常多留意,建立安全意識,養成一種習慣,一些基本的安全當然也不會佔用用 coding 的時間。養成這個習慣,即便在專案急,時間短的情況一下,依然可以做的品質很高。不要等到自己以後負責的東西,資料庫都被拿走了,造成損失才重視。共勉!

相關文章:

php防止sql注入的方法詳解

php防止sql注入的函數介紹

以上是PHP防止sql注入的方法解說的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn