大多數 PHP 程序員對 MySQL 確定不陌生,至於各類 MySQL 函數的用法在開發手冊和 w3school 這類網站上也有不少介紹。可是,你所用的寫法真的安全嗎?面對愈來愈猖獗的黑客攻擊,SQL 注入防範很是重要,因此使用 MySQL 也要有更正確的姿式。php
SQL Injection:就是經過把 SQL 命令插入到 Web 表單遞交或輸入域名或頁面請求的查詢字符串,最終達到欺騙服務器執行惡意的 SQL 命令。html
具體來講,它是利用現有應用程序,將(惡意)的 SQL 命令注入到後臺數據庫引擎執行的能力,它能夠經過在 Web 表單中輸入(惡意)SQL 語句獲得一個存在安全漏洞的網站上的數據庫,而不是按照設計者意圖去執行 SQL 語句。mysql
在網上能夠搜到一些簡單例子,經過一步步有目的地調整 url 請求參數,讓 server 返回其 MySQL 數據結構及內容,以達到獲取敏感數據的目的。程序員
開發者要使用合適的數據庫操做函數,這一點也是開發手冊和教程上不多提到的。
舉個例子,要實現一個簡單的查詢功能,通常會這樣寫:sql
<?php $con = mysql_connect("localhost","mysql_user","mysql_pwd"); if (!$con) { die('Could not connect: ' . mysql_error()); } $username = $_POST['user']; $password = $_POST['pwd']; $sql = "SELECT * FROM Person WHERE username=$username AND password=$password"; mysql_query($sql,$con); // 一些代碼 mysql_close($con); ?>
這種用法至關不安全,若是被人盯上,會很容易地進行 sql 注入
因此有很多人推薦使用 mysql_real_escape_string,寫法以下:數據庫
<?php $con = mysql_connect("localhost","mysql_user","mysql_pwd"); if (!$con) { die('Could not connect: ' . mysql_error()); } $username = $_POST['user']; $password = $_POST['pwd']; // 若是不是數字則加引號 $username = "'" . mysql_real_escape_string($username) . "'"; $password = "'" . mysql_real_escape_string($password) . "'"; $sql = "SELECT * FROM Person WHERE username=$username AND password=$password"; mysql_query($sql,$con); // 一些代碼 mysql_close($con); ?>
這種方法安全性比第一種更高,但對方仍是能夠利用編碼的漏洞來實現輸入任意密碼就能登陸服務器的注入攻擊。另外像一些 str_replace,addslashes 或者使用 magic_quotes_gpc 選項之類的方法,不是已經失效就是仍然有可能被破解。安全
然而百度一下「PHP 防注入」,仍然有不少文章在介紹上述辦法。因此咱們這裏要鄭重提示你們這個風險,提醒全部後來者繞過這個坑。服務器
那麼,現在還能倖免於注入的方法就是 Prepared Statement 機制了。這裏推薦你們使用 mysqli 方式,mysql 擴展已經在 php5.5 中被廢棄,在 php7 中更是直接不支持。爲向高版本兼容考慮,新代碼儘可能使用 mysqli
最終的查詢代碼就變成了這樣:php7
<?php $mysqli=new mysqli("localhost","mysql_user","mysql_pwd"); if (mysqli_connect_errno()) { printf("Connect failed: %s\n", mysqli_connect_error()); exit(); } $username = $_POST['user']; $password = $_POST['pwd']; if ($stmt = $mysqli->prepare("SELECT * FROM Person WHERE username=? AND password=?")) { $stmt->bind_param("ss",$username,$password); $stmt->execute(); } // 一些代碼 $mysqli->close(); ?>
把全部操做 MySQL 的代碼都重構成上面這樣,那麼面對 SQL 注入就能夠高枕無憂了。另外 pdo 也有 Prepared Statement 機制,一樣可以保護數據庫,有興趣的同窗能夠本身嘗試一下。數據結構
OneAPM for PHP 可以深刻到全部 PHP 應用內部完成應用性能管理 可以深刻到全部 PHP 應用內部完成應用性能管理和監控,包括代碼級別性能問題的可見性、性能瓶頸的快速識別與追溯、真實用戶體驗監控、服務器監控和端到端的應用性能管理。想閱讀更多技術文章,請訪問 OneAPM 官方技術博客。
本文轉自 OneAPM 官方博客