① php中防止sql注入的最好方法是什麼
使用預備義語句和參數化查詢。對於帶有任何參數的sql語句都會被發送到資料庫伺服器,並被解析!對於攻擊者想要惡意注入sql是不可能的! 實現這一目標基本上有兩種選擇: 1.使用PDO(PHP Data Objects ):$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(PHP數據對象) 注意當使用PDO訪問MySQL資料庫真正的預備義語句並不是默認使用的!為了解決這個問題,你必須禁用模擬准備好的語句。使用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);在上面例子中錯誤模式ERRMODE不是嚴格必須的,但是建議添加它。當運行出錯產生致命錯誤時,這種方法腳本不會停止。並給開發人員捕捉任何錯誤的機會(當拋出PDOException異常時)。 setAttribute()那一行是強制性的,它告訴PDO禁用模擬預備義語句,使用真正的預備義語句。這可以確保語句和值在發送給MySQL資料庫伺服器前不被PHP解析(攻擊者沒有機會注入惡意的SQL). 當然你可以在構造函數選項中設置字元集參數,特別注意'老'的PHP版本(5.3.6)會在DSN中忽略掉字元集參數。 這里最重要的是,該參數值是和預編譯的語句結合的,而不是和一個SQL字元串.SQL注入的工作原理是通過欺騙手段創建的SQL腳本包括惡意字元串發送到資料庫.因此,通過發送實際的分開的sql參數,你會降低風險.使用准備好的語句時,你發送的任何參數,將只被視為字元串(雖然資料庫引擎可能會做一些參數的優化,當然最終可能會為數字).在上面的例子中,如果變數$name包含'sarah';DELETE * FROM employees,結果只會是一個搜索的字元串"'sarah';DELETE * FROM employees",你不會得到一個空表。 使用准備好的語句的另一個好處是,如果你在同一會話中多次執行相同的語句,這將只被解析和編譯一次,給你一些的速度增長。
② PHP PDO驅動問題,怎麼解決
最簡單的方法把這個預編譯寫法是把SQL指令預先放到SQL伺服器,命令執行的時候在動態的傳遞數據
這個寫法的一個好處是安全,防止SQL注入,因為放了一個問號,就已經表示那是數據而不是一個SQL可執行的語句
第二個好處是可以一次編譯多次執行,在執行多個相似操作的時候,會加快SQL的速度,降低SQL伺服器的負擔就這樣試試吧,如果你對php有興趣的話,可以向我一樣在後盾人平台多看看自己學習學習,時間長了自己就慢慢明白了,希望能幫到你,給個採納吧謝謝o(〒㉨〒)o
③ 如何實現php的安全最大化怎樣避免sql注入漏洞和xss跨站腳本攻擊漏洞
使用php安全模式
伺服器要做好管理,賬號許可權是否合理。
假定所有用戶的輸入都是「惡意」的,防止XSS攻擊,譬如:對用戶的輸入輸出做好必要的過濾
防止CSRF,表單設置隱藏域,post一個隨機字元串到後台,可以有效防止跨站請求偽造。
防禦SQL注入。
避免SQL注入漏洞
1.使用預編譯語句
2.使用安全的存儲過程
3.檢查輸入數據的數據類型
4.從資料庫自身的角度考慮,應該使用最小許可權原則,不可使用root或dbowner的身份連接資料庫。若多個應用使用同一個資料庫,也應該為資料庫分配不同的賬戶。web應用使用的資料庫賬戶,不應該有創建自定義函數,操作本地文件的許可權。
避免XSS跨站腳本攻擊
1.假定所有用戶輸入都是「邪惡」的
2.考慮周全的正則表達式
3.為cookie設置HttpOnly,防止cookie劫持
4.外部js不一定可靠
5.出去不必要的HTML注釋
6. 針對非法的HTML代碼包括單雙引號等,使用htmlspecialchars()函數。
④ PHP的SQL漏洞修復!【中危漏洞】SQL_Injection_Vulnerability【編號:3303280】
攻擊方法就在:
request:{"body":"ClassID=1+and%281%3D1%29","header":"POST /m/dianhua.asp HTTP 1.1
Content-Length: 24
/m/dianhua.asp這里,即你要修復的位置。
⑤ php 使用mysql 的prepare預編譯,下面這段代碼有防sql注入的功能么請高手賜教
sql注入怎麼回事:說白了就是在一個單引號上做文章,你把單引號轉義就沒啥問題了,預編譯就是把這些字元轉義後插入,其中包括單引號。
這段可以防止.
⑥ php7中為什麼不能用
1. 不要使用 mysql_ 函數
這一天終於來了,從此你不僅僅「不應該」使用mysql_函數。PHP 7 已經把它們從核心中全部移除了,也就是說你需要遷移到好得多的mysqli_函數,或者更靈活的 PDO 實現。
2. 不要編寫垃圾代碼
這一條可能易於理解,但是會變得越來越重要,因為 PHP 7 的速度提升可能會隱藏你的一些問題。不要僅僅滿足於你的站點速度,因為遷移到 PHP 7 才讓它變快。
為了理解速度有多重要,以及如何把事情做得更好,請看一看我們的文章速度優化入門指南。
作為一名開發者,你應該總是確保按需載入腳本,盡可能連接它們,編寫高效的資料庫查詢,盡可能使用緩存,以及其它。
3. 不要在文件末尾使用 PHP 閉合標簽
你可以看一看,當一個文件以 PHP 代碼結尾時,WordPress 多數核心代碼都把末尾的 PHP 標簽去掉了。實際上,Zend 框架特別禁止了它。PHP 並不需要文件末尾的閉合標簽,並且我們可以通過去掉它來保證不會在後面添加任何的空白字元。
4. 不要做不必要的引用傳遞
我個人不喜歡引用傳遞。我知道有時候它很實用,但是其它情況下它使代碼變得難懂,並且更難預測結果。
據說一些人認為它使代碼運行更快,但是根據一些 PHP 高級程序員所說,這並不正確。
說明引用為什麼不好的一個例子是,PHP 內建了shuffle()和sort()。它們修改原始數組,而不是返回處理後的數組,這很不合邏輯。
5. 不要在循環中執行查詢
在循環中執行查詢非常浪費。它給你的系統施加不必要的壓力,並且可能能夠在循環外部更快獲得相同結果。當我遇到需要這樣的情況時,我通常會使用兩個分離的查詢來解決問題,我會使用它們來構建數據數組。之後我會遍歷數組,並不需要在這個過程中執行查詢。
由於 WordPress 適用於這里,它可能有一些例外。雖然get_post_meta() 會從資料庫獲取大量數據,如果你正在遍歷某個特殊博文的元數據你可以在循環中使用它。這是因為當你第一次調用它的時候,WordPress實際上會獲取所有元數據並緩存它們。後續的調用使用這些緩存數據,沒有資料庫的調用。
弄懂這些的最佳方式是閱讀函數文檔,以及使用類似 Query Monitor 的工具。
6. 不要在 SQL 查詢中使用 *
當然,這個更像 MySQL 的問題,但是我們習慣在 PHP 中編寫 SQL 代碼,所以都差不多。無論如何,如果可以避免的話,不要在 SQL 查詢里使用通配符,尤其是資料庫有很多列的時候。
你應該明確指定需要哪些行,並且僅僅獲取它們。這有助於減少所用資源,保護數據,以及讓事情變得盡可能清晰。
對於 SQL,你需要了解所有可用的函數,並且盡可能測試其速度。在計算均值、求和或計算類似數值時,要使用 SQL 函數而不是 PHP 函數。如果你不確定某個查詢的速度,測試它並且嘗試一些其它的編譯 — 之後使用最好的那個。
7. 不要信任用戶輸入
信任用戶輸入是不明智的。始終校驗、過濾、轉義、檢查並留好退路。用戶數據存在三個問題:我們開發者並沒有考慮每種可能性,它通常不正確,以及它可能是蓄意破壞。
經過周密考慮的系統可以防護這些威脅。要確保使用類似filter_var()的內建函數檢查適當的值,以及在處理資料庫時轉義(或預編譯)。
WordPress 擁有一些函數來解決問題。詳見文章校驗、轉義和過濾用戶數據。
8. 不要故作聰明
你的目標應該是編寫優雅的代碼,來更清晰地表達你的意圖。你可能能夠通過將任何東西縮短為一個單詞的變數,使用多層的三元邏輯,以及其它手段,從每個頁面中優化 0.01 秒。但這只會給你和你周圍的人產生大麻煩。
合理命名變數,為代碼編寫文檔,優先選擇清晰而不是簡潔。甚至還可以更好,使用標準的面向對象代碼,它本身或多或少就是文檔,不需要一大堆內聯數值。
9. 不要重新發明輪子
PHP 到現在為止有很長時間了,網站被造出來的時間更長。很可能無論你需要造出什麼,一些人之前早就造出來了。不要害怕向他人尋求支持,Github是你的好朋友,Composer也是,Packagist也是。
從日誌工具到調色工具,從性能分析器到單元測試框架,從 Mailchimp API 到 Twitter Bootstrap,每個東西都可以通過按下按鍵(或者敲下命令)來獲取,使用它們吧!
10. 不要忽略其它語言
如果你是個 PHP 程序員,現在有個好機會去至少了解 HTML、CSS、JavaScript 和 MySQL。當你能夠更好地處理這些語言時,就是重新學習 JavaScript 的時機了。JavaScript 並不是 jQuery,你應該合理地學習 JavaScript 來更高效地使用它。
我也打算向你推薦學習面向對象的 PHP,它可以節省時間,並且在代碼規模更大時會變得更好。對於類似 C# 和 Java 的語言,在你了解 OOP 之後,它們也更易於理解。
通過了解包管理器、構建腳本、CoffeeScript、LESS、SASS、YAML 、腳本引擎和其它強大的工具來擴展你的知識面。我強烈向你推薦看一看其它框架,尤其是 Laravel。
當你使用它們出色完成任務時,學習 Ruby、RoR、Android、iPhone 和 Windows Phone 應用開發如何?你可能會認為這毫無意義,因為它們在你的舒適區和工作所需范圍之外,但是這就是它們的意義。每種語言都有一些要學習的實用的東西,以及從沒碰到的新知識。所有 PHP 頂級開發者都懂得很多其它編程語言,這並非偶然。
⑦ php7中為什麼不能用
PHP(外文名:PHP: Hypertext Preprocessor,中文名:「超文本預處理器」)是一種通用開源腳本語言。語法吸收了C語言、Java和Perl的特點,利於學習,使用廣泛,主要適用於Web開發領域。PHP 獨特的語法混合了C、Java、Perl以及PHP自創的語法。它可以比CGI或者Perl更快速地執行動態網頁。用PHP做出的動態頁面與其他的編程語言相比,PHP是將程序嵌入到HTML(標准通用標記語言下的一個應用)文檔中去執行,執行效率比完全生成HTML標記的CGI要高許多;PHP還可以執行編譯後代碼,編譯可以達到加密和優化代碼運行,使代碼運行更快。
php7
1. 不要使用 mysql_ 函數
這一天終於來了,從此你不僅僅「不應該」使用mysql_函數。PHP 7 已經把它們從核心中全部移除了,也就是說你需要遷移到好得多的mysqli_函數,或者更靈活的 PDO 實現。
2. 不要編寫垃圾代碼
這一條可能易於理解,但是會變得越來越重要,因為 PHP 7 的速度提升可能會隱藏你的一些問題。不要僅僅滿足於你的站點速度,因為遷移到 PHP 7 才讓它變快。
為了理解速度有多重要,以及如何把事情做得更好,請看一看我們的文章速度優化入門指南。
作為一名開發者,你應該總是確保按需載入腳本,盡可能連接它們,編寫高效的資料庫查詢,盡可能使用緩存,以及其它。
3. 不要在文件末尾使用 PHP 閉合標簽
你可以看一看,當一個文件以 PHP 代碼結尾時,WordPress 多數核心代碼都把末尾的 PHP 標簽去掉了。實際上,Zend 框架特別禁止了它。PHP 並不需要文件末尾的閉合標簽,並且我們可以通過去掉它來保證不會在後面添加任何的空白字元。
4. 不要做不必要的引用傳遞
我個人不喜歡引用傳遞。我知道有時候它很實用,但是其它情況下它使代碼變得難懂,並且更難預測結果。
據說一些人認為它使代碼運行更快,但是根據一些 PHP 高級程序員所說,這並不正確。
說明引用為什麼不好的一個例子是,PHP 內建了shuffle()和sort()。它們修改原始數組,而不是返回處理後的數組,這很不合邏輯。
5. 不要在循環中執行查詢
在循環中執行查詢非常浪費。它給你的系統施加不必要的壓力,並且可能能夠在循環外部更快獲得相同結果。當我遇到需要這樣的情況時,我通常會使用兩個分離的查詢來解決問題,我會使用它們來構建數據數組。之後我會遍歷數組,並不需要在這個過程中執行查詢。
由於 WordPress 適用於這里,它可能有一些例外。雖然get_post_meta() 會從資料庫獲取大量數據,如果你正在遍歷某個特殊博文的元數據你可以在循環中使用它。這是因為當你第一次調用它的時候,WordPress實際上會獲取所有元數據並緩存它們。後續的調用使用這些緩存數據,沒有資料庫的調用。
弄懂這些的最佳方式是閱讀函數文檔,以及使用類似 Query Monitor 的工具。
6. 不要在 SQL 查詢中使用 *
當然,這個更像 MySQL 的問題,但是我們習慣在 PHP 中編寫 SQL 代碼,所以都差不多。無論如何,如果可以避免的話,不要在SQL 查詢里使用通配符,尤其是資料庫有很多列的時候。
你應該明確指定需要哪些行,並且僅僅獲取它們。這有助於減少所用資源,保護數據,以及讓事情變得盡可能清晰。
對於 SQL,你需要了解所有可用的函數,並且盡可能測試其速度。在計算均值、求和或計算類似數值時,要使用 SQL 函數而不是PHP 函數。如果你不確定某個查詢的速度,測試它並且嘗試一些其它的編譯 — 之後使用最好的那個。
7. 不要信任用戶輸入
信任用戶輸入是不明智的。始終校驗、過濾、轉義、檢查並留好退路。用戶數據存在三個問題:我們開發者並沒有考慮每種可能性,它通常不正確,以及它可能是蓄意破壞。
經過周密考慮的系統可以防護這些威脅。要確保使用類似filter_var()的內建函數檢查適當的值,以及在處理資料庫時轉義(或預編譯)。
WordPress 擁有一些函數來解決問題。詳見文章校驗、轉義和過濾用戶數據。
8. 不要故作聰明
你的目標應該是編寫優雅的代碼,來更清晰地表達你的意圖。你可能能夠通過將任何東西縮短為一個單詞的變數,使用多層的三元邏輯,以及其它手段,從每個頁面中優化 0.01 秒。但這只會給你和你周圍的人產生大麻煩。
合理命名變數,為代碼編寫文檔,優先選擇清晰而不是簡潔。甚至還可以更好,使用標準的面向對象代碼,它本身或多或少就是文檔,不需要一大堆內聯數值。
9. 不要重新發明輪子
PHP 到現在為止有很長時間了,網站被造出來的時間更長。很可能無論你需要造出什麼,一些人之前早就造出來了。不要害怕向他人尋求支持,Github是你的好朋友,Composer也是,Packagist也是。
從日誌工具到調色工具,從性能分析器到單元測試框架,從 Mailchimp API 到 Twitter Bootstrap,每個東西都可以通過按下按鍵(或者敲下命令)來獲取,使用它們吧!
10. 不要忽略其它語言
如果你是個 PHP 程序員,現在有個好機會去至少了解 HTML、CSS、JavaScript 和 MySQL。當你能夠更好地處理這些語言時,就是重新學習 JavaScript 的時機了。JavaScript 並不是 jQuery,你應該合理地學習 JavaScript 來更高效地使用它。
我也打算向你推薦學習面向對象的 PHP,它可以節省時間,並且在代碼規模更大時會變得更好。對於類似 C# 和 Java 的語言,在你了解 OOP 之後,它們也更易於理解。
通過了解包管理器、構建腳本、CoffeeScript、LESS、SASS、YAML 、腳本引擎和其它強大的工具來擴展你的知識面。我強烈向你推薦看一看其它框架,尤其是 Laravel。
當你使用它們出色完成任務時,學習 Ruby、RoR、Android、iPhone 和 Windows Phone 應用開發如何?你可能會認為這毫無意義,因為它們在你的舒適區和工作所需范圍之外,但是這就是它們的意義。每種語言都有一些要學習的實用的東西,以及從沒碰到的新知識。所有 PHP 頂級開發者都懂得很多其它編程語言,這並非偶然。
⑧ php防sql注入的代碼
一、 注入式攻擊的類型
可能存在許多不同類型的攻擊動機,但是乍看上去,似乎存在更多的類型。這是非常真實的-如果惡意用戶發現了一個能夠執行多個查詢的辦法的話。本文後面,我們會對此作詳細討論。
如
果你的腳本正在執行一個SELECT指令,那麼,攻擊者可以強迫顯示一個表格中的每一行記錄-通過把一個例如"1=1"這樣的條件注入到WHERE子句中,如下所示(其中,注入部分以粗體顯示):
SELECT * FROM wines WHERE variety = 』lagrein』 OR 1=1;』
正如我們在前面所討論的,這本身可能是很有用的信息,因為它揭示了該表格的一般結構(這是一條普通的記錄所不能實現的),以及潛在地顯示包含機密信息的記錄。
一條更新指令潛在地具有更直接的威脅。通過把其它屬性放到SET子句中,一名攻擊者可以修改當前被更新的記錄中的任何欄位,例如下面的例子(其中,注入部分以粗體顯示):
UPDATE wines SET type=』red』,』vintage』=』9999』 WHERE variety = 』lagrein』
通過把一個例如1=1這樣的恆真條件添加到一條更新指令的WHERE子句中,這種修改范圍可以擴展到每一條記錄,例如下面的例子(其中,注入部分以粗體顯示):
UPDATE wines SET type=』red』,』vintage』=』9999 WHERE variety = 』lagrein』 OR 1=1;』
最危險的指令可能是DELETE-這是不難想像的。其注入技術與我們已經看到的相同-通過修改WHERE子句來擴展受影響的記錄的范圍,例如下面的例子(其中,注入部分以粗體顯示):
DELETE FROM wines WHERE variety = 』lagrein』 OR 1=1;』
二、 多個查詢注入
多個查詢注入將會加劇一個攻擊者可能引起的潛在的損壞-通過允許多條破壞性指令包括在一個查詢中。在使用MySQL資料庫時, 攻擊者通過把一個出乎意料之外的終止符插入到查詢中即可很容易實現這一點-此時一個注入的引號(單引號或雙引號)標記期望變數的結尾;然後使用一個分號終 止該指令。現在,一個另外的攻擊指令可能被添加到現在終止的原始指令的結尾。最終的破壞性查詢可能看起來如下所示:
SELECT * FROM wines WHERE variety = 』lagrein』;
GRANT ALL ON *.* TO 』BadGuy@%』 IDENTIFIED BY 』gotcha』;』
這個注入將創建一個新的用戶BadGuy並賦予其網路特權(在所有的表格上具有所有的特權);其中,還有一個"不祥"的口令被加入到這個簡單的SELECT語句中。如果你遵循我們在以前文章中的建議-嚴格限制該過程用戶的特權,那麼,這應該無法工作,因為web伺服器守護程序不再擁有你撤回的GRANT特權。但是從理論上講,這樣的一個攻擊可能給予BadGuy自由權力來實現他對你的資料庫的任何操作。
至 於這樣的一個多查詢是否會被MySQL伺服器處理,結論並不唯一。這其中的一些原因可能是由於不同版本的MySQL所致,但是大多數情況卻是由於多查詢存 在的方式所致。MySQL的監視程序完全允許這樣的一個查詢。常用的MySQL GUI-phpMyAdmin,在最終查詢之前會復制出以前所有的內容,並且僅僅這樣做。
但是,大多數的在一個注入上下文中的多查詢都是由PHP的mysql 擴展負責管理的。幸好,默認情況下,它是不允許在一個查詢中執行多個指令的;試圖執行兩個指令(例如上面所示的注入)將會簡單地導致失敗-不設置任何錯 誤,並且沒有生成任何輸出信息。在這種情況下,盡管PHP也只是"規規矩矩"地實現其預設行為,但是確實能夠保護你免於大多數簡單的注入式攻擊。
PHP5中的新的mysqli擴展(參考http://php.net/mysqli),就象mysql一樣,內在地也不支持多個查詢,不過卻提供了一個mysqli_multi_query()函數以支持你實現多查詢-如果你確實想這樣做的話。
然而,對於SQLite-與PHP5綁定到一起的可嵌入的SQL資料庫引擎(參考http://sqlite.org/和http://php.net/sqlite) 情況更為可怕,由於其易於使用而吸引了大量用戶的關注。在有些情況下,SQLite預設地允許這樣的多指令查詢,因為該資料庫可以優化批查詢,特別是非常 有效的批INSERT語句處理。然而,如果查詢的結果為你的腳本所使用的話(例如在使用一個SELECT語句檢索記錄的情況下), sqlite_query()函數卻不會允許執行多個查詢。三、 INVISION Power BOARD SQL注入脆弱性
Invision Power Board是一個著名的論壇系統。2005年五月6號,在登錄代碼中發現了一處SQL注入脆弱性。其發現
者為GulfTech Security Research的James Bercegay。
這個登錄查詢如下所示:
$DB->query("SELECT * FROM ibf_members WHERE id=$mid AND password=』$pid』");
其中,成員ID變數$mid和口令ID變數$pid被使用下面兩行代碼從my_cookie()函數中檢索出:
$mid = intval($std->my_getcookie(』member_id』));
$pid = $std->my_getcookie(』pass_hash』);
在此,my_cookie()函數使用下列語句從cookie中檢索要求的變數:
return urldecode($_COOKIE[$ibforums->vars[』cookie_id』].$name]);
【注意】從該cookie返回的值根本沒有被處理。盡管$mid在使用於查詢之前被強制轉換成一個整數,但是$pid卻保持不變。因此,它很容易遭受我們前面所討論的注入類型的攻擊。
因此,通過以如下方式修改my_cookie()函數,這種脆弱性就會暴露出來:
if ( ! in_array( $name,array(』topicsread』, 』forum_read』,』collapseprefs』) ) )
{
return $this->
clean_value(urldecode($_COOKIE[$ibforums->vars[』cookie_id』].$name]));
else
{
return urldecode($_COOKIE[$ibforums->vars[』cookie_id』].$name]);
}
經過這樣的改正之後,其中的關鍵變數在"通過"全局clean_value()函數後被返回,而其它變數卻未進行檢查。
現 在,既然我們大致了解了什麼是SQL注入,它的注入原理以及這種注入的脆弱程度,那麼接下來,讓我們探討如何有效地預防它。幸好,PHP為我們提供了豐富 的資源,因此我們有充分的信心預言,一個經仔細地徹底地使用我們所推薦的技術構建的應用程序將會從你的腳本中根本上消除任何可能性的SQL注入-通過在它 可能造成任何損壞之前"清理"你的用戶的數據來實現。
四、 界定你的查詢中的每一個值
我們推薦,你確保界定了你的查詢中的每一個值。字元串值首當其沖,以及那些你通常期望應該使用"單"(而不是"雙")引號的內容。一方面,如果你使用雙引 號來允許PHP在字元串內的變數替代,這樣可以使得輸入查詢更為容易些;另一方面,這(無可否認,只是極少量地)也會減少以後PHP代碼的分析工作。
下面,讓我們使用我們一開始使用的那個非注入式查詢來說明這個問題:
SELECT * FROM wines WHERE variety = 』lagrein』
或以PHP語句表達為:
$query = "SELECT * FROM wines WHERE variety = 』$variety』";
從技術上講,引號對於數字值來說是不需要使用的。但是,如果你並不介意用引號把例如葡萄酒這樣的一個域相應的一個值括起來並且如果你的用戶把一個空值輸入到你的表單中的話,那麼,你會看到一個類似下面的查詢:
SELECT * FROM wines WHERE vintage =
當然,這個查詢從語法上講是無效的;但是,下面的語法卻是有效的:
SELECT * FROM wines WHERE vintage = 』』
第二個查詢將(大概)不會返回任何果,但是至少它不會返回一個錯誤消息。
五、 檢查用戶提交的值的類型
從前面的討論中我們看到,迄今為止,SQL注入的主要來源往往出在一個意料之外的表單入口上。然而,當你經由一個表單向用戶提供機會提交某些值時,你應該有相當的優勢來確
定 你想取得什麼樣的輸入內容-這可以使得我們比較容易地檢查用戶入口的有效性。在以前的文章中,我們已經討論過這樣的校驗問題;所以,在此,我們僅簡單地總 結當時我們討論的要點。如果你正在期望一個數字,那麼你可以使用下面這些技術之一來確保你得到的真正是一個數字類型:
�6�1 使用is_int()函數(或is_integer()或is_long())。
�6�1 使用gettype()函數。
�6�1 使用intval()函數。
�6�1 使用settype()函數。
為 了檢查用戶輸入內容的長度,你可以使用strlen()函數。為了檢查一個期望的時間或日期是否有效,你可以使用strtotime()函數。它幾乎一定 能夠確保一位用戶的入口中沒有包含分號字元(除非標點符號可以被合法地包括在內)。你可以藉助於strpos()函數容易地實現這一點,如下所示:if( strpos( $variety, 』;』 ) ) exit ( "$variety is an invalid value for variety!" );
正如我們在前面所提到的,只要你仔細分析你的用戶輸入期望,那麼,你應該能夠很容易地檢查出其中存在的許多問題。
六、 從你的查詢中濾去每一個可疑字元
盡管在以前的文章中,我們已經討論過如何過濾掉危險字元的問題;但是在此,還是讓我們再次簡單地強調並歸納一下這個問題:
�6�1 不要使用magic_quotes_gpc指令或它的"幕後搭擋"-addslashes()函數,此函數在應用程序開發中是被限制使用的,並且此函數還要求使用額外的步驟-使用stripslashes()函數。
�6�1 相比之下,mysql_real_escape_string()函數更為常用,但是也有它自己的缺點。
⑨ 為什麼大型網站前端使用 PHP 後台邏輯用 Java
最近糾結了一下,如果開發一個大型的網站,我到底應該使用php還是jsp,後台到底使用php還是用java,我的選擇要麼是php要麼是java,因為我喜歡linux、unix,當然window平台也必須支持,以便哦的妹紙可以查看。這就要求用一些跨平台相當好的軟體+工具+語言,所以選擇只能是這么幾個。最後我的決定是php+java,一個前台一個後台,理由如下: php和java在開源社區的活躍度嚴重超過了其他的語言,使用人數也都是相當之多;活躍的開發工程師們能夠給我幫助,且這倆都能很好的跨平台,不用花費大量的人力物力去維護 我也做過一個物聯網的網關網站,比較復雜,當時採用的是jsp+java,復雜程度可想而知,單單說開發過程,網站部分繁瑣,每次想查看結果運行網站的時候還需要重新打包部署一下,嚴重影響了哦的開發效率,每天的時間都是在等待(因為網站比較復雜,打包部署需要浪費一些時間)。相對來說呢,php就沒有了,php靈活,好學,上手快,容易修改,容易發布,關鍵是熱部署,這個真讓哦眼睛大亮。當然看待任何事物都需要兩種眼光,php也會有缺點,比如沒有太好的開發IDE,所以拼寫錯誤很正常,且php的sql注入危險較大點,執行效率不高,安全性不如java。還有一些理由,來自知乎的米米們給的建議: Java的優點則是穩定可靠、運行效率高(尤其是JIT的出現之後差距更大了)、不容易犯錯(強類型、預編譯、必須攔截異常等等),缺點是開發和發布的效率相對較低。盡管優秀的工程師能在一定程度上改變以上的問題,但通常而言,哪能到處都是高手多如狗的夢之隊? 從MVC的層次結構上說,在一般網站項目的開發周期中,需求變更最頻繁、調整最多的是View,其次是Controller,最後是Model。這非常好理解,沒事干誰天天改數據結構?每次版本升級控制結構都要改的啦,或多或少而已。再次是兩者之間的通信,目前RPC技術已經足夠成熟,無論是Web Service/Hessian/RESTful API都能夠讓開發人員專注在功能開發上,而不需要過多的考慮異構平台的差異和通訊的細節。這也就意味著在大公司里同時應用兩種語言的方案並不會引入過多的復雜度和工作量。當然,文檔量的下限倒是因此被拔高了不少,但事實上大部分團隊對此其實都是喜聞樂見的:別每天說文檔重要但沒空了,你不寫其他同事怎麼配合? 靠近用戶的前端,使用PHP能夠更快的完成前端頻繁而瑣碎的更新,自如的應對各種需求的變化。頁面的結構調整、用戶輸入內容的基本驗證、僅只和用戶交互有關的簡單邏輯等都很適合使用PHP來開發,甚至可以通過類似Smarty等模板技術將其頁面的變動遷移到前端團隊。而基本的業務邏輯和數據的更新採用Java開發,可以有效的提高復用度、提升性能和吞吐能力、規避安全問題等。而開發效率稍有降低換來的是可維護性的提升,發布速度慢就更不是問題了,因為通常對於基礎業務邏輯的調整往往都是整體修改,並層層測試確認才能發布的。 所以,大型網站前端採用PHP後端採用Java,既好招人又好維護、系統穩定還性能高、連安全性都大大增加。代碼復用、文檔完備度居然也都改善了。讓你在以上這些好處觸手可及時,對架構師知識譜系在廣度上要求更高一些這事根本就不是個問題。 單一方案其實一樣可以做良好的隔離,PHP同樣可以提供Service,而性能問題其實很多時候是演算法和架構的問題而不是語言差異的問題。如Velocity或JSTL等也是很優秀的隔離方案。 但這些方案在高壓力下會暴露出很多問題而體現雙語言的優勢,這些在上面其實都提到,詳細說明一些很難得到改變的點: 1. PHP由於其動態腳本語言的特性,包括類、函數、常量在內都需要在每次請求周期中重復執行後才能建立運行環境;為了保證解析速度而犧牲編譯質量;應用了FastCGI但僅僅只是復用進程處理請求減少fork成本而不是像其他語言,初始化完畢後通過FastCGI的介面獲得數據並以對應介面返回數據等幾個原因,基本上已經不可能在性能上追回當初更爛現在開著JIT牌跑車的Java了。 2. 在PHP里是如此的容易犯錯而難以發現,即使你用實質上出自官方的Zend Studio,也無法改變一個事實:要保證你的程序高質量無大錯,得要有充足的經驗、足夠的嚴謹、以及——負責任的QA。淘寶的黃裳就曾經拿IDE這事開過玩笑。而玩笑背後的那個原因「缺乏中間件」最近幾年有不少的改善,主要是不少中間件的支持變得更廣泛了從而讓PHP得益,但發展的根源其實還是在C和Java社區。性能和易犯錯則是語言特性造成的技術難點,也是用來換取靈活、快捷的必要代價,很難去指望有根本的改善。 3. Java的世界裡也有JSTL、Velocity和Freemaker等,但和PHP靈活而強大的動態能力、豐富的函數和類庫、輕松的學習成本、多到令人發指的文檔相比,簡直就是渣,就是渣啊!JSTL改完了要重啟Context啊有木有?Velocity不關緩存也要重啟啊有木有?Velocity開緩存性能低下啊有木有?即使這些都不管,調整下某個數據校驗規則要改Action也要重啟有木有? 實際工作中性能問題可以通過良好的架構解決,容易犯錯的問題可以通過框架和規范以及全面的測試來解決,中間件選擇少些但其實該有的都有了,Java的靈活性一樣有不少可供考慮的解決方案哪怕是挫得要死的摘掉節點重啟,完成後重新上節點的策略。 所以,大家會看到單一語言的技術團隊也很多,這個問題的真正考慮還是更多在團隊自身的特點、積累等等。用了雙語言的,也知道自己為什麼要用這些,不用的也清楚自己的路該怎麼走。最後的最後說一句:如果你不知道自己為什麼要用雙語言方案的話,基本上你也就不需要考慮它了。從知乎上整理得到上文 我的Email:[email protected]
⑩ 為什麼 PHP 應該使用 PDO 方式訪問資料庫
很多程序員都學習過如何使用 MySQL 或 MySQLi 擴展訪問資料庫。在 PHP 5.1 中,有一個更好的方法。PHP Data Objects(PDO) 提供了很多預處理語句的方法,且使用對象將使你的工作更有成效!
PDO 介紹
「PDO – PHP Data Objects – 是一個對多種資料庫提供統一操作方法的資料庫訪問層。」
它並不具備資料庫特有的語法,但它將使切換資料庫和平台更加容易,多數情況下,只需要簡單修改鏈接字元串。
這並非一篇完整教導如何使用SQL的教程。它重要為那些現今仍在使用 mysql 或 mysqli 擴展的人,幫助他們躍至更具可移植性和強力的 PDO。
資料庫支持
此擴展可以使用 PDO 驅動編寫過的所有資料庫。在本文書寫時,下面的資料庫支持已經實現:
PDO_DBLIB ( FreeTDS / Microsoft SQL Server / Sybase )
PDO_FIREBIRD ( Firebird/Interbase 6 )
PDO_IBM ( IBM DB2 )
PDO_INFORMIX ( IBM Informix Dynamic Server )
PDO_MYSQL ( MySQL 3.x/4.x/5.x )
PDO_OCI ( Oracle Call Interface )
PDO_ODBC ( ODBC v3 (IBM DB2, unixODBC and win32 ODBC) )
PDO_PGSQL ( PostgreSQL )
PDO_SQLITE ( SQLite 3 and SQLite 2 )
PDO_4D ( 4D )
你的系統不會也不必支持所有上面的驅動;下面是一個快速檢查所支持資料庫的方法:
1 print_r(PDO::getAvailableDrivers());
連接
不同資料庫的連接方法可能稍有不同,下面是一些較為流行的資料庫連接方法。你將注意到,雖然資料庫類型不同,前三種資料庫的連接方式是相同的——而 SQLite 使用自己的語法。
Connection String
01 try {
02 # MS SQL Server andSybase with PDO_DBLIB
03 $DBH = newPDO("mssql:host=$host;dbname=$dbname, $user, $pass");
04 $DBH = newPDO("sybase:host=$host;dbname=$dbname, $user, $pass");
05
06 # MySQL with PDO_MYSQL
07 $DBH = newPDO("mysql:host=$host;dbname=$dbname", $user, $pass);
08
09 # SQLite Database
10 $DBH = newPDO("sqlite:my/database/path/database.db");
11 }
12 catch(PDOException $e) {
13 echo$e->getMessage();
14 }
注意 try/catch 塊——你應該總是使用 try/catch 包裝你的 PDO 操作,並使用異常機制——這里只是簡單的示例。通常,你只需要一個連接——有很多可以教你語法的列表。 $DBH 代表「資料庫句柄」,這將貫穿全文。
通過將句柄設置為 NULL,你可以關閉任一連接。
1 # close the connection
2 $DBH = null;
你可以在PHP.net找到更多資料庫特定選項和/或其它資料庫連接字元串的信息。
異常與 PDO
PDO 可以使用異常處理錯誤,這意味著你的所有 PDO 操作都應當包裝在一個 try/catch 塊中。你可以通過設定錯誤模式屬性強制 PDO 在新建的句柄中使用三種錯誤模式中的某一個。下面是語法:
1 $DBH->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT );
2 $DBH->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING );
3 $DBH->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
無論你設定哪個錯誤模式,一個錯誤的連接總會產生一個異常,因此創建連接應該總是包裝在 try/catch 塊中。
PDO::ERRMODE_SILENT
這是默認的錯誤模式。如果你使用這個模式,你將得使用同 mysql 或 mysqli 擴展一樣的方法差錯。其它兩種模式更適合 DRY 編程。
PDO::ERRMODE_WARNING
此方法將會發出一個標准PHP警告,並允許程序繼續運行。這對調試很有幫助。
PDO::ERRMODE_EXCEPTION
這是多數情況下你所希望的方式。它生成異常,允許你更容易的處理錯誤,隱藏可能導致它人了解你系統的信息。下面是一個充分利用異常的示例:
01 # connect to the database
02 try {
03 $DBH = newPDO("mysql:host=$host;dbname=$dbname", $user, $pass);
04 $DBH->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
05
06 # UH-OH! Typed DELECT instead of SELECT!
07 $DBH->prepare('DELECT name FROM people');
08 }
09 catch(PDOException $e) {
10 echo"I'm sorry, Dave. I'm afraid I can't do that.";
11 file_put_contents('PDOErrors.txt', $e->getMessage(), FILE_APPEND);
12 }
在 select 語句中有一個故意留下的錯誤;這將導致一個異常。異常錯誤細節保存至一個 log 文件,並生成一段友好的(或不怎麼友好的)信息於用戶。
插入和更新
插入新數據,更新已存數據是一種非常常見的資料庫操作。使用 PDO,這通常需要兩個步驟。本節中所述的所有內容對更新和插入都有效。
這里有一個最基本的插入示例:
1 # STH means "Statement Handle"
2 $STH = $DBH->prepare("INSERT INTO folks ( first_name ) values ( 'Cathy' )");
3 $STH->execute();
你也可以使用 exec() 完成相同的操作,這將減少調用。多數情況下,你會使用調用多的方法,以充分利用語句預處理的優勢。即使你只用它一次,使用語句預處理,幫助你保護你的 SQL 免於注入攻擊。
預處理語句
使用語句預處理將幫助你免於SQL注入攻擊。
一條預處理語句是一條預編譯的 SQL 語句,它可以使用多次,每次只需將數據傳至伺服器。其額外優勢在於可以對使用佔位符的數據進行安全處理,防止SQL注入攻擊。
你通過在 SQL 語句中使用佔位符的方法使用預處理語句。下面是三個例子:一個沒有佔位符,一個使用無名佔位符,一個使用命名佔位符。
1 # no placeholders - ripe for SQL Injection!
2 $STH = $DBH->("INSERT INTO folks (name, addr, city) values ($name, $addr, $city)");
3
4 # unnamed placeholders
5 $STH = $DBH->("INSERT INTO folks (name, addr, city) values (?, ?, ?);
6
7 # named placeholders
8 $STH = $DBH->("INSERT INTO folks (name, addr, city) value (:name, :addr, :city)");
你希望避免第一種方法。選擇命名我無名佔位符將會對你對語句中數據的設置產生影響。
無名佔位符
01 # assign variables to each place holder, indexed 1-3
02 $STH->bindParam(1, $name);
03 $STH->bindParam(2, $addr);
04 $STH->bindParam(3, $city);
05
06 # insert one row
07 $name = "Daniel"
08 $addr = "1 Wicked Way";
09 $city = "Arlington Heights";
10 $STH->execute();
11
12 # insert another row with different values
13 $name = "Steve"
14 $addr = "5 Circle Drive";
15 $city = "Schaumburg";
16 $STH->execute();
這里有兩步。首先,我們對各個佔位符指定變數(2-4行)。然後,我們對各個佔位符指定數據,並執行語句。要發送另一組數據,只需改變這些變數的值並再次執行語句。
這種方法看上去對擁有很多參數的語句很笨拙吧?的確。然而,當數據保存於數組中時,這非常容易簡略:
1 # the data we want to insert
2 $data = array('Cathy', '9 Dark and Twisty Road', 'Cardiff');
3
4 $STH = $DBH->("INSERT INTO folks (name, addr, city) values (?, ?, ?);
5 $STH->execute($data);
容易吧!
數組中的數據按順序填入佔位符中。 $data[0]是第一個,$data[1]是第二個,依次。不過,要是數組中數據的次序不正確,這將不能正常運行,你需要先對數組排序。
命名佔位符
你可能已經開始猜測語法了,不過下面就是示例:
1 # the first argument is the named placeholder name - notice named
2 # placeholders always start with a colon.
3 $STH->bindParam(':name', $name);
你可以看使用快捷方式,但它需使用關聯數組。下面是示例:
1 # the data we want to insert
2 $data = array( 'name' => 'Cathy', 'addr' => '9 Dark and Twisty', 'city' => 'Cardiff' );
3
4 # the shortcut!
5 $STH = $DBH->("INSERT INTO folks (name, addr, city) value (:name, :addr, :city)");
6 $STH->execute($data);
數組中的鍵不需要以冒號開頭,但其它部分需要同佔位符匹配。如果你有一個二維數組,你只需遍歷它,並對遍歷的每個數組執行語句。
命名佔位符的另一個好的功能是直接將對象插入到你的資料庫中,只要屬性同命名欄位匹配。下面是一個示例對象,以及如何將它插入到資料庫中的示例:
01 # a simple object
02 class person {
03 public $name;
04 public $addr;
05 public $city;
06
07 function __construct($n,$a,$c) {
08 $this->name = $n;
09 $this->addr = $a;
10 $this->city = $c;
11 }
12 # etc ...
13 }
14
15 $cathy = new person('Cathy','9 Dark and Twisty','Cardiff');
16
17 # here's the fun part:
18 $STH = $DBH->("INSERT INTO folks (name, addr, city) value (:name, :addr, :city)");
19 $STH->execute((array)$cathy);
通過在執行時將對象轉換為數組,輸將將會同數組的鍵一樣對待。