有一點我們必須承認,大多數web應用程序都離不開session的使用。這篇文章將會結合php以及http協議來分析如何建立一個安全的會話管理機制。我們先簡單的了解一些http的知識,從而理解該協議的無狀態特性。然后,學習一些關于cookie的基本操作。最后,我會一步步闡述如何使用一些簡單,高效的方法來提高你的php應用程序的安全性以及穩定行。
我想大多數的php初級程序員一定會認為php默認的session機制的安全性似乎是有一定保障的,事實恰好相反 - php團隊只是提供了一套便捷的session的解決方案提供給程序員使用,至于安全性的話,應該由程序員來加強,這是應用程序開發團隊的責任。因為,這里面的方法很多,可以這么說吧,沒有最好,只有更好。攻擊的方式在不斷變化,防守方也需要不斷變招,所以,我個人認為php團隊的做法還是比較明智的。
無狀態性
Http是一種無狀態性的協議。這是因為此種協議不要求瀏覽器在每次請求中標明它自己的身份,并且瀏覽器以及服務器之間并沒有保持一個持久性的連接用于多個頁面之間的訪問。當一個用戶訪問一個站點的時候,用戶的瀏覽器發送一個http請求到服務器,服務器返回給瀏覽器一個http響應。其實很簡單的一個概念,客戶端一個請求,服務器端一個回復,這就是整個基于http協議的通訊過程。
因為web應用程序是基于http協議進行通訊的,而我們已經講過了http是無狀態的,這就增加了維護web應用程序狀態的難度, 對于開發者來說,是一個不小的挑戰。Cookies是作為http的一個擴展誕生的,其主要用途是彌補http的無狀態特性,提供了一種保持客戶端與服務器端之間狀態的途徑,但是由于出于安全性的考慮,有的用戶在瀏覽器中是禁止掉cookie的。這種情況下,狀態信息只能通過url中的參數來傳遞到服務器端,不過這種方式的安全性很差。事實上,按照通常的想法,應該有客戶端來表明自己的身份,從而和服務器之間維持一種狀態,但是出于安全性方面的考慮,我們都應該明白一點 - 來自客戶端的信息都是不能完全信任的。
盡管這樣,針對維持web應用程序狀態的問題,相對來說,還是有比較優雅的解決方案的。不過,應該說是沒有完美的解決方案的,再好的解決方案也不可能適用所有的情況。這篇文章將介紹一些技術。這些技術可以用來比較穩定地維持應用程序的狀態以及抵御一些針對session的攻擊,比如會話劫持。并且你可以學習到cookie是怎樣工作的,php 的session做了那些事情,以及怎樣才能劫持session。
HTTP 概覽
如何才能保持web應用程序的狀態以及選擇最合適的解決方案呢?在回答這個問題之前,必須得先了解web的底層協議 - Hypertext Transfer Protocol (HTTP)。
當用戶訪問http://example.com這個域名的時候,瀏覽器就會自動和服務器建立tcp/ip連接,然后發送http請求到example.com的服務器的80端口。該個請求的語法如下所示:
GET / HTTP/1.1
Host: example.org
以上第一行叫做請求行,第二個參數(一個反斜線在這個例子中)表示所請求資源的路徑。反斜線代表了根目錄;服務器會轉換這個根目錄為服務器文件系統中的一個具體目錄。
Apache的用戶常用DocumentRoot這個命令來設置這個文檔根路徑。如果請求的url是http://example.org/path/to/script.php,那么請求的路徑就是/path/to/script.php。假如document root 被定義為usr/lcoal/apache/htdocs的話,整個請求的資源路徑就是/usr/local/apache/htdocs/path/to/script.php。
第二行描述的是http頭部的語法。在這個例子中的頭部是Host, 它標識了瀏覽器希望獲取資源的域名主機。還有很多其它的請求頭部可以包含在http請求中,比如user-Agent頭部,在php可以通過$_SERVER['HTTP_USER_AGENT']獲取請求中所攜帶的這個頭部信息。
但是遺憾的是,在這個請求例子中,沒有任何信息可以唯一標識當前這個發出請求的客戶端。有些開發者借助請求中的ip頭部來唯一標識發出此次請求的客戶端,但是這種方式存在很多問題。因為,有些用戶是通過代理來訪問的,比如用戶A通過代理B連接網站www.example.com, 服務器端獲取的ip信息是代理B分配給A的ip地址,如果用戶這時斷開代理,然后再次連接代理的話,它的代理ip地址又再次改變,也就說一個用戶對應了多個ip地址,這種情況下,服務器端根據ip地址來標識用戶的話,會認為請求是來自不同的用戶,事實上是同一個用戶。 還用另外一種情況就是,比如很多用戶是在同一個局域網里通過路由連接互聯網,然后都訪問www.example.com 的話,由于這些用戶共享同一個外網ip地址,這會導致服務器認為這些用戶是同一個用戶發出的請求,因為他們是來自同一個ip地址的訪問。
保持應用程序狀態的第一步就是要知道如何來唯一地標識每個客戶端。因為只有在http中請求中攜帶的信息才能用來標識客戶端,所以在請求中必須包含某種可以用來標識客戶端唯一身份的信息。Cookie設計出來就是用來解決這一問題的。
Cookies
如果你把Cookies看成為http協議的一個擴展的話,理解起來就容易的多了,其實本質上cookies就是http的一個擴展。有兩個http頭部是專門負責設置以及發送cookie的,它們分別是Set-Cookie以及Cookie。當服務器返回給客戶端一個http響應信息時,其中如果包含Set-Cookie這個頭部時,意思就是指示客戶端建立一個cookie,并且在后續的http請求中自動發送這個cookie到服務器端,直到這個cookie過期。如果cookie的生存時間是整個會話期間的話,那么瀏覽器會將cookie保存在內存中,瀏覽器關閉時就會自動清除這個cookie。另外一種情況就是保存在客戶端的硬盤中,瀏覽器關閉的話,該cookie也不會被清除,下次打開瀏覽器訪問對應網站時,這個cookie就會自動再次發送到服務器端。一個cookie的設置以及發送過程分為以下四步:
客戶端發送一個http請求到服務器端
服務器端發送一個http響應到客戶端,其中包含Set-Cookie頭部
客戶端發送一個http請求到服務器端,其中包含Cookie頭部
服務器端發送一個http響應到客戶端
這個通訊過程也可以用以下下示意圖來描述:
原文轉自:http://blogread.cn/it/article/6004?f=wb1