国产欧美日韩第一页|日本一二三不卡视频|在线精品小视频,亚洲第一免费播放区,metcn人体亚洲一区,亚洲精品午夜视频

Session的本質(zhì)

2017-05-15 17:37:12 9289

有一點(diǎn)我們必須承認(rèn),大多數(shù)web應(yīng)用程序都離不開session的使用。這篇文章將會(huì)結(jié)合php以及http協(xié)議來(lái)分析如何建立一個(gè)安全的會(huì)話管理機(jī)制。我們先簡(jiǎn)單的了解一些http的知識(shí),從而理解該協(xié)議的無(wú)狀態(tài)特性。然后,學(xué)習(xí)一些關(guān)于cookie的基本操作。最后,我會(huì)一步步闡述如何使用一些簡(jiǎn)單,高效的方法來(lái)提高你的php應(yīng)用程序的安全性以及穩(wěn)定行。

我想大多數(shù)的php初級(jí)程序員一定會(huì)認(rèn)為php默認(rèn)的session機(jī)制的安全性似乎是有一定保障的,事實(shí)恰好相反 php團(tuán)隊(duì)只是提供了一套便捷的session的解決方案提供給程序員使用,至于安全性的話,應(yīng)該由程序員來(lái)加強(qiáng),這是應(yīng)用程序開發(fā)團(tuán)隊(duì)的責(zé)任。因?yàn)?,這里面的方法很多,可以這么說(shuō)吧,沒(méi)有最好,只有更好。攻擊的方式在不斷變化,防守方也需要不斷變招,所以,我個(gè)人認(rèn)為php團(tuán)隊(duì)的做法還是比較明智的。

 

無(wú)狀態(tài)性

Http是一種無(wú)狀態(tài)性的協(xié)議。這是因?yàn)榇朔N協(xié)議不要求瀏覽器在每次請(qǐng)求中標(biāo)明它自己的身份,并且瀏覽器以及服務(wù)器之間并沒(méi)有保持一個(gè)持久性的連接用于多個(gè)頁(yè)面之間的訪問(wèn)。當(dāng)一個(gè)用戶訪問(wèn)一個(gè)站點(diǎn)的時(shí)候,用戶的瀏覽器發(fā)送一個(gè)http請(qǐng)求到服務(wù)器,服務(wù)器返回給瀏覽器一個(gè)http響應(yīng)。其實(shí)很簡(jiǎn)單的一個(gè)概念,客戶端一個(gè)請(qǐng)求,服務(wù)器端一個(gè)回復(fù),這就是整個(gè)基于http協(xié)議的通訊過(guò)程。

因?yàn)?/span>web應(yīng)用程序是基于http協(xié)議進(jìn)行通訊的,而我們已經(jīng)講過(guò)了http是無(wú)狀態(tài)的,這就增加了維護(hù)web應(yīng)用程序狀態(tài)的難度, 對(duì)于開發(fā)者來(lái)說(shuō),是一個(gè)不小的挑戰(zhàn)。Cookies是作為http的一個(gè)擴(kuò)展誕生的,其主要用途是彌補(bǔ)http的無(wú)狀態(tài)特性,提供了一種保持客戶端與服務(wù)器端之間狀態(tài)的途徑,但是由于出于安全性的考慮,有的用戶在瀏覽器中是禁止掉cookie的。這種情況下,狀態(tài)信息只能通過(guò)url中的參數(shù)來(lái)傳遞到服務(wù)器端,不過(guò)這種方式的安全性很差。事實(shí)上,按照通常的想法,應(yīng)該有客戶端來(lái)表明自己的身份,從而和服務(wù)器之間維持一種狀態(tài),但是出于安全性方面的考慮,我們都應(yīng)該明白一點(diǎn) 來(lái)自客戶端的信息都是不能完全信任的。

盡管這樣,針對(duì)維持web應(yīng)用程序狀態(tài)的問(wèn)題,相對(duì)來(lái)說(shuō),還是有比較優(yōu)雅的解決方案的。不過(guò),應(yīng)該說(shuō)是沒(méi)有完美的解決方案的,再好的解決方案也不可能適用所有的情況。這篇文章將介紹一些技術(shù)。這些技術(shù)可以用來(lái)比較穩(wěn)定地維持應(yīng)用程序的狀態(tài)以及抵御一些針對(duì)session的攻擊,比如會(huì)話劫持。并且你可以學(xué)習(xí)到cookie是怎樣工作的,php session做了那些事情,以及怎樣才能劫持session

 

HTTP 概覽

如何才能保持web應(yīng)用程序的狀態(tài)以及選擇最合適的解決方案呢?在回答這個(gè)問(wèn)題之前,必須得先了解web的底層協(xié)議 Hypertext Transfer Protocol (HTTP)。

當(dāng)用戶訪問(wèn)http://www.tjdsmy.cn這個(gè)域名的時(shí)候,瀏覽器就會(huì)自動(dòng)和服務(wù)器建立tcp/ip連接,然后發(fā)送http請(qǐng)求到example.com的服務(wù)器的80端口。該個(gè)請(qǐng)求的語(yǔ)法如下所示:GET / HTTP/1.1

Host: example.org

以上第一行叫做請(qǐng)求行,第二個(gè)參數(shù)(一個(gè)反斜線在這個(gè)例子中)表示所請(qǐng)求資源的路徑。反斜線代表了根目錄;服務(wù)器會(huì)轉(zhuǎn)換這個(gè)根目錄為服務(wù)器文件系統(tǒng)中的一個(gè)具體目錄。

Apache的用戶常用DocumentRoot這個(gè)命令來(lái)設(shè)置這個(gè)文檔根路徑。如果請(qǐng)求的urlhttp://www.tjdsmy.cn/path/to/script.php,那么請(qǐng)求的路徑就是/path/to/script.php。假如document root 被定義為usr/lcoal/apache/htdocs的話,整個(gè)請(qǐng)求的資源路徑就是/usr/local/apache/htdocs/path/to/script.php。

第二行描述的是http頭部的語(yǔ)法。在這個(gè)例子中的頭部是Host, 它標(biāo)識(shí)了瀏覽器希望獲取資源的域名主機(jī)。還有很多其它的請(qǐng)求頭部可以包含在http請(qǐng)求中,比如user-Agent頭部,在php可以通過(guò)$_SERVER['HTTP_USER_AGENT']獲取請(qǐng)求中所攜帶的這個(gè)頭部信息。

但是遺憾的是,在這個(gè)請(qǐng)求例子中,沒(méi)有任何信息可以唯一標(biāo)識(shí)當(dāng)前這個(gè)發(fā)出請(qǐng)求的客戶端。有些開發(fā)者借助請(qǐng)求中的ip頭部來(lái)唯一標(biāo)識(shí)發(fā)出此次請(qǐng)求的客戶端,但是這種方式存在很多問(wèn)題。因?yàn)?,有些用戶是通過(guò)代理來(lái)訪問(wèn)的,比如用戶A通過(guò)代理B連接網(wǎng)站www.tjdsmy.cn, 服務(wù)器端獲取的ip信息是代理B分配給Aip地址,如果用戶這時(shí)斷開代理,然后再次連接代理的話,它的代理ip地址又再次改變,也就說(shuō)一個(gè)用戶對(duì)應(yīng)了多個(gè)ip地址,這種情況下,服務(wù)器端根據(jù)ip地址來(lái)標(biāo)識(shí)用戶的話,會(huì)認(rèn)為請(qǐng)求是來(lái)自不同的用戶,事實(shí)上是同一個(gè)用戶。 還用另外一種情況就是,比如很多用戶是在同一個(gè)局域網(wǎng)里通過(guò)路由連接互聯(lián)網(wǎng),然后都訪問(wèn)www.tjdsmy.cn的話,由于這些用戶共享同一個(gè)外網(wǎng)ip地址,這會(huì)導(dǎo)致服務(wù)器認(rèn)為這些用戶是同一個(gè)用戶發(fā)出的請(qǐng)求,因?yàn)樗麄兪莵?lái)自同一個(gè)ip地址的訪問(wèn)。

保持應(yīng)用程序狀態(tài)的第一步就是要知道如何來(lái)唯一地標(biāo)識(shí)每個(gè)客戶端。因?yàn)橹挥性?/span>http中請(qǐng)求中攜帶的信息才能用來(lái)標(biāo)識(shí)客戶端,所以在請(qǐng)求中必須包含某種可以用來(lái)標(biāo)識(shí)客戶端唯一身份的信息。Cookie設(shè)計(jì)出來(lái)就是用來(lái)解決這一問(wèn)題的。

 

Cookies

如果你把Cookies看成為http協(xié)議的一個(gè)擴(kuò)展的話,理解起來(lái)就容易的多了,其實(shí)本質(zhì)上cookies就是http的一個(gè)擴(kuò)展。有兩個(gè)http頭部是專門負(fù)責(zé)設(shè)置以及發(fā)送cookie,它們分別是Set-Cookie以及Cookie。當(dāng)服務(wù)器返回給客戶端一個(gè)http響應(yīng)信息時(shí),其中如果包含Set-Cookie這個(gè)頭部時(shí),意思就是指示客戶端建立一個(gè)cookie,并且在后續(xù)的http請(qǐng)求中自動(dòng)發(fā)送這個(gè)cookie到服務(wù)器端,直到這個(gè)cookie過(guò)期。如果cookie的生存時(shí)間是整個(gè)會(huì)話期間的話,那么瀏覽器會(huì)將cookie保存在內(nèi)存中,瀏覽器關(guān)閉時(shí)就會(huì)自動(dòng)清除這個(gè)cookie。另外一種情況就是保存在客戶端的硬盤中,瀏覽器關(guān)閉的話,該cookie也不會(huì)被清除,下次打開瀏覽器訪問(wèn)對(duì)應(yīng)網(wǎng)站時(shí),這個(gè)cookie就會(huì)自動(dòng)再次發(fā)送到服務(wù)器端。一個(gè)cookie的設(shè)置以及發(fā)送過(guò)程分為以下四步:

客戶端發(fā)送一個(gè)http請(qǐng)求到服務(wù)器端

服務(wù)器端發(fā)送一個(gè)http響應(yīng)到客戶端,其中包含Set-Cookie頭部

客戶端發(fā)送一個(gè)http請(qǐng)求到服務(wù)器端,其中包含Cookie頭部

服務(wù)器端發(fā)送一個(gè)http響應(yīng)到客戶端

這個(gè)通訊過(guò)程也可以用以下下示意圖來(lái)描述:

blob.png

在客戶端的第二次請(qǐng)求中包含的Cookie頭部中,提供給了服務(wù)器端可以用來(lái)唯一標(biāo)識(shí)客戶端身份的信息。這時(shí),服務(wù)器端也就可以判斷客戶端是否啟用了cookies。盡管,用戶可能在和應(yīng)用程序交互的過(guò)程中突然禁用cookies的使用,但是,這個(gè)情況基本是不太可能發(fā)生的,所以可以不加以考慮,這在實(shí)踐中也被證明是對(duì)的。

 

GET and POST Data

除了cookies,客戶端還可以將發(fā)送給服務(wù)器的數(shù)據(jù)包含在請(qǐng)求的url中,比如請(qǐng)求的參數(shù)或者請(qǐng)求的路徑中。 我們來(lái)看一個(gè)例子:

GET /index.php?foo=bar HTTP/1.1

Host: example.org

以上就是一個(gè)常規(guī)的http get 請(qǐng)求,該get請(qǐng)求發(fā)送到example.org域名對(duì)應(yīng)的web 服務(wù)器下的index.php腳本, index.php腳本中,可以通過(guò)$_GET['foo']來(lái)獲取對(duì)應(yīng)的urlfoo參數(shù)的值,也就是’bar’。大多數(shù)php開發(fā)者都稱這樣的數(shù)據(jù)會(huì)GET數(shù)據(jù),也有少數(shù)稱它為查詢數(shù)據(jù)或者url變量。但是大家需要注意一點(diǎn),不是說(shuō)GET數(shù)據(jù)就只能包含在HTTP GET類型的請(qǐng)求中,在HTTP POST類型的請(qǐng)求中同樣可以包含GET數(shù)據(jù),只要將相關(guān)GET數(shù)據(jù)包含在請(qǐng)求的url中即可,也就是說(shuō)GET數(shù)據(jù)的傳遞不依賴與具體請(qǐng)求的類型。

另外一種客戶端傳遞數(shù)據(jù)到服務(wù)器端的方式是將數(shù)據(jù)包含在http請(qǐng)求的內(nèi)容區(qū)域內(nèi)。 這種方式需要請(qǐng)求的類型是POST的,看下面一個(gè)例子:

POST /index.php HTTP/1.1

Host: example.org

Content-Type: application/x-www-form-urlencoded

Content-Length: 7

foo=bar

在這種情況下,在腳本index.php可以通過(guò)調(diào)用$_POST['foo']來(lái)獲取對(duì)應(yīng)的值bar。開發(fā)者稱這個(gè)數(shù)據(jù)為POST數(shù)據(jù),也就是大家熟知的formpost方式提交請(qǐng)求的方式。

在一個(gè)請(qǐng)求中,可以同時(shí)包含這兩種形式的數(shù)據(jù):

POST /index.php?myget=foo HTTP/1.1

Host: example.orgContent-Type: application/x-www-form-urlencoded

Content-Length: 11

mypost=bar

這兩種傳遞數(shù)據(jù)的方式,比起用cookies來(lái)傳遞數(shù)據(jù)更穩(wěn)定,因?yàn)?/span>cookie可能被禁用,但是以GET以及POST方式傳遞數(shù)據(jù)時(shí),不存在這種情況。我們可以將PHPSESSID包含在http請(qǐng)求的url中,就像下面的例子一樣:

GET /index.php?PHPSESSID=12345 HTTP/1.1

Host: example.org

以這種方式傳遞session id的話,可以跟用cookie頭部傳遞session id一樣,達(dá)到同樣的效果, 但是,缺點(diǎn)就是需要開發(fā)者認(rèn)為地將session id附加在url中或者作為隱藏字段加入到表單中。不像cookie一樣,只要服務(wù)器端指示客戶端創(chuàng)建cookie成功以后,客戶端在后續(xù)的請(qǐng)求中,會(huì)自動(dòng)第將對(duì)應(yīng)的沒(méi)有過(guò)期的cookie傳遞給服務(wù)器端。當(dāng)然,php在開啟session.use_trans_sid后,也可以自動(dòng)地將session id 附加在url中以及表單的隱藏字段中,但是這個(gè)選項(xiàng)不建議開啟,因?yàn)榇嬖诎踩珕?wèn)題。這樣的話,容易泄露session id, 比如有的用戶會(huì)bookmark一個(gè)url或者分享一個(gè)url,那么session id也就暴露了,加入這個(gè)session id還沒(méi)有過(guò)期,那是有一定的安全問(wèn)題存在的,除非服務(wù)器端,除了session id外,還附加了其它方式進(jìn)行驗(yàn)證用戶的合法性!

盡管以POST的方式來(lái)傳遞session id的話,相對(duì)GET的方式來(lái)說(shuō),會(huì)安全的多。但是,這種方式的缺點(diǎn)就是比較麻煩,因?yàn)檫@樣的話,在你的應(yīng)用程序中比較將所有的請(qǐng)求都轉(zhuǎn)換成post的請(qǐng)求,這顯然是不太合適的。

 

Session的管理

直到現(xiàn)在,我只討論了如何維護(hù)應(yīng)用程序的狀態(tài),只是簡(jiǎn)單地涉及到了如果保持請(qǐng)求之間的關(guān)系。接下來(lái),我闡述下在實(shí)際中用到比較多的技術(shù) Session的管理。涉及到session的管理,就不是單單地維持各個(gè)請(qǐng)求之間的狀態(tài),還需要維持會(huì)話期間針對(duì)每個(gè)特定用戶使用到的數(shù)據(jù)。我們常常把這種數(shù)據(jù)叫做session數(shù)據(jù),因?yàn)檫@些數(shù)據(jù)是跟某個(gè)特定用戶與服務(wù)器之間的會(huì)話相關(guān)聯(lián)的。如果你使用php內(nèi)置的session的管理機(jī)制,那么session數(shù)據(jù)一般是保存在/tmp這個(gè)服務(wù)器端的文件夾中,并且其中的session數(shù)據(jù)會(huì)被自動(dòng)地保存到超級(jí)數(shù)組$_SESSION中。一個(gè)最簡(jiǎn)單的使用session的例子,就是將相關(guān)的session數(shù)據(jù)從一個(gè)頁(yè)面?zhèn)鬟f(注意:實(shí)際傳遞的是session id)到另一個(gè)頁(yè)面。下面用示例代碼1, start.php, 對(duì)這個(gè)    例子加以演示:

<?php 

session_start(); 

$_SESSION['foo'] = 'bar'; 

?> 

<a href="continue.php">continue.php</a> 

假如用戶點(diǎn)擊start.php中的鏈接訪問(wèn)continue.php,那么在continue.php中就可以通過(guò)$_SESSION['foo']獲取在start.php中的定義的值’bar’??聪旅娴氖纠a2:

示例代碼2 continue.php

<?php 

session_start(); 

echo $_SESSION['foo']; /* bar */ 

?> 

是不是非常簡(jiǎn)單,但是我要指出的話,如果你真的這樣來(lái)寫代碼的話,說(shuō)明你對(duì)php底層的對(duì)于session的實(shí)現(xiàn)機(jī)制還不是非常了解透徹。在不了解php內(nèi)部給你自動(dòng)做了多少事情的情況下,你會(huì)發(fā)現(xiàn)如果程序出錯(cuò)的話,這樣的代碼將變的很難調(diào)試,事實(shí)上,這樣的代碼也完全沒(méi)有安全性可言。

 

Session的安全性問(wèn)題

一直以來(lái)很多開發(fā)者都認(rèn)為php內(nèi)置的session管理機(jī)制是具有一定的安全性,可以對(duì)一般的session攻擊起到防御。事實(shí)上,這是一種誤解,php團(tuán)隊(duì)只實(shí)現(xiàn)了一種方便有效的機(jī)制。具體的安全措施,應(yīng)該有應(yīng)用程序的開發(fā)團(tuán)隊(duì)來(lái)實(shí)施。 就像開篇談到的,沒(méi)有最好的解決方案,只有最合適你的方案。

現(xiàn)在,我們來(lái)看下一個(gè)比較常規(guī)的針對(duì)session的攻擊:

用戶訪問(wèn)http://www.tjdsmy.cn,并且登錄。

example.org的服務(wù)器設(shè)置指示客戶端設(shè)置相關(guān)cookie PHPSESSID=12345

攻擊者這時(shí)訪問(wèn)http://www.tjdsmy.cn/,并且在請(qǐng)求中攜帶了對(duì)應(yīng)的cookie PHPSESSID=12345

這樣情況下,因?yàn)?/span>example.orge的服務(wù)器通過(guò)PHPSESSID來(lái)辨認(rèn)對(duì)應(yīng)的用戶的,所以服務(wù)器錯(cuò)把攻擊者當(dāng)成了合法的用戶。

整個(gè)過(guò)程的描述,請(qǐng)看下面的示例圖:

blob.png

當(dāng)然這種攻擊的方式,前提條件是攻擊者必須通過(guò)某種手段固定,劫持或者猜測(cè)出某個(gè)合法用戶的PHPSESSID。雖然這看起來(lái)難度很高,但是也不是不可能的事情。

 

安全性的加強(qiáng)

有很多技術(shù)可以用來(lái)加強(qiáng)Session的安全性,主要思想就是要使驗(yàn)證的過(guò)程對(duì)于合法用戶來(lái)說(shuō),越簡(jiǎn)單越好,然后對(duì)于攻擊者來(lái)說(shuō),步驟要越復(fù)雜越好。當(dāng)然,這似乎是比較難于平衡的,要根據(jù)你應(yīng)用程序的具體設(shè)計(jì)來(lái)做決策。

最簡(jiǎn)單的居于HTTP/1.1請(qǐng)求包括請(qǐng)求行以及一些Host的頭部:

GET / HTTP/1.1

Host: example.org

如果客戶端通過(guò)PHPSESSID傳遞相關(guān)的session標(biāo)識(shí)符,可以將PHPSESSID放在cookie頭部中進(jìn)行傳遞:

GET / HTTP/1.1

Host: example.org

Cookie: PHPSESSID=12345

同樣地,客戶端也可以將session標(biāo)識(shí)符放在請(qǐng)求的url中進(jìn)行傳遞。

GET /?PHPSESSID=12345

HTTP/1.1Host: example.org

當(dāng)然,session標(biāo)識(shí)符也可以包含在POST數(shù)據(jù)中,但是這對(duì)用戶體驗(yàn)有影響,所以這種方式很少采用。

因?yàn)閬?lái)自TCP/IP信息也不一定可以完全信任的,所以,對(duì)于web開發(fā)者來(lái)說(shuō),利用TCP/IP中的信息來(lái)加強(qiáng)安全性也是不太合適的。 不過(guò),攻擊者也必須提供一個(gè)合法用戶的唯一的標(biāo)識(shí)符,才能假扮成合法用戶進(jìn)入系統(tǒng)。因此,看起來(lái)唯一能夠有效的保護(hù)系統(tǒng)的措施,就是盡量地隱藏session標(biāo)識(shí)符或者使之難于猜測(cè)出來(lái)。最好就是兩者都能實(shí)施。

PHP會(huì)自動(dòng)生成一個(gè)隨機(jī)的session ID,基本來(lái)說(shuō)是不可能被猜測(cè)出來(lái)的,所以這方面的安全還是有一定保障的。但是,要防止攻擊者獲取一個(gè)合法的session ID是相當(dāng)困難的,這基本上不是開發(fā)者所能控制的。

事實(shí)上,許多情況下都有可能導(dǎo)致session ID的泄露。 比如說(shuō),如果通過(guò)GET數(shù)據(jù)來(lái)傳遞session ID的話,就有可能暴露這個(gè)敏感的身份信息。因?yàn)?,有的用戶可能?huì)將帶有session ID的鏈接緩存,收藏或者發(fā)送在郵件內(nèi)容中。Cookies是一種像相對(duì)來(lái)說(shuō)安全一點(diǎn)的機(jī)制,但是用戶是可以在客戶端中禁止掉cookies!在一些IE的版本中也有比較嚴(yán)重的安全漏洞,比較有名的就是會(huì)泄露cookies給一些有安全隱患的邪惡站點(diǎn)。

因此,作為一個(gè)開發(fā)者,可以肯定session ID是不能被猜測(cè)出來(lái)的,但是還是有可能被攻擊者使用某些方法獲取到。所以,必須采取一些額外的安全措施來(lái)防止此類情況在你的應(yīng)用程序中發(fā)生。

實(shí)際上,一個(gè)標(biāo)準(zhǔn)的HTTP請(qǐng)求中除了Host等必須包含的頭部,還包含了一些可選的頭部.舉一個(gè)例子,看下面的一個(gè)請(qǐng)求:

GET / HTTP/1.1

Host: example.org

Cookie: PHPSESSID=12345

User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X; en-US; rv:1.8.1.1) Gecko/20061204 Firefox/2.0.0.1

Accept: text/html;q=0.9, */*;q=0.1

Accept-Charset: ISO-8859-1, utf-8;q=0.66, *;q=0.66

Accept-Language: en

我們可以看到,在以上的一個(gè)請(qǐng)求例子中包含了四個(gè)額外的頭部,分別是User-Agent, Accept, Accept-Charset以及Accept-Language。因?yàn)檫@些頭部不是必須的,所以完全依賴他們?cè)谀愕膽?yīng)用程序中發(fā)揮作用是不太明智的。但是,如果一個(gè)用戶的瀏覽器確實(shí)發(fā)送了這些頭部到服務(wù)器,那么可以肯定的是在接下來(lái)的同一個(gè)用戶通過(guò)同一個(gè)瀏覽器發(fā)送的請(qǐng)求中,必然也會(huì)攜帶這些頭部。當(dāng)然,這其中也會(huì)有極少數(shù)的特殊情況發(fā)生。假如以上例子是由一個(gè)當(dāng)前的跟服務(wù)器建立了會(huì)話的用戶發(fā)出的請(qǐng)求,考慮下面的一個(gè)請(qǐng)求:

GET / HTTP/1.1

Host: example.org

Cookie: PHPSESSID=12345

User-Agent: Mozilla/5.0

因?yàn)橛邢嗤?/span>session id包含在請(qǐng)求的Cookie頭部中,所以相同的php session將會(huì)被訪問(wèn)到。但是,請(qǐng)求里的User-Agent頭部跟先前的請(qǐng)求中的信息是不同的,系統(tǒng)是否可以假定這兩個(gè)請(qǐng)求是同一個(gè)用戶發(fā)出的?

像這種情況下,發(fā)現(xiàn)瀏覽器的頭部改變了,但是不能肯定這是否是一次來(lái)自攻擊者的請(qǐng)求的話,比較好的措施就是彈出一個(gè)要求輸入密碼的輸入框讓用戶輸入,這樣的話,對(duì)用戶體驗(yàn)的影響不會(huì)很大,又能很有效地防止攻擊。

當(dāng)然,你可以在系統(tǒng)中加入核查User-Agent頭部的代碼,類似示例3中的代碼:

示例代碼3

<?php  

session_start();  

if (md5($_SERVER['HTTP_USER_AGENT']) != $_SESSION['HTTP_USER_AGENT'])  

{&nbsp;&nbsp;/* 彈出密碼輸入框 */&nbsp;&nbsp;exit; 

}  

?> 

當(dāng)然,你先必須在第一次請(qǐng)求時(shí),初始化session的時(shí)候,用MD5算法加密user agent信息并且保存在session中,類似下面示例4中的代碼:

示例代碼4

<?php  

session_start();  

$_SESSION['HTTP_USER_AGENT'] = md5($_SERVER['HTTP_USER_AGENT']);  

?> 

雖然不一定需要用MD5來(lái)加密這個(gè)User-Agent信息,但使用這種方式以后就不需要再過(guò)濾這個(gè)$_SERVER['HTTP_USER_AGENT']數(shù)據(jù)了。不然的話,在使用這個(gè)數(shù)據(jù)以前必須要進(jìn)行數(shù)據(jù)過(guò)濾,因?yàn)槿魏蝸?lái)自客戶端的數(shù)據(jù)都是不可信任的,必須要注意這一點(diǎn)。

在你檢查這個(gè)User-Agent客戶端頭部信息以后,做為一個(gè)攻擊者必須要完成兩步才能劫持一個(gè)session:

獲取一個(gè)合法的session id

包含一個(gè)相同的User-Agent頭部在偽造的請(qǐng)求中

你可能會(huì)說(shuō),居然攻擊者能獲得有效的session id,那么以他的水平,偽造一個(gè)相同的User-Agent不是件難事。不錯(cuò),但是我們可以說(shuō)這至少給他添加了一些麻煩,在一定程度上也增加了session機(jī)制的安全性。

你應(yīng)該也能想到了,既然我們可以檢查User-Agent這個(gè)頭部來(lái)加強(qiáng)安全性,那么不妨再利用其它的一些頭部信息,把他們組合起來(lái)生成一個(gè)加密的token,并且讓客戶端在后續(xù)的請(qǐng)求中攜帶這個(gè)token!這樣的話,攻擊者基本上不可能猜測(cè)出這樣一個(gè)token是怎么生成出來(lái)的。這好比你用信用卡在超市付款,一個(gè)你必須有信用卡(好比session id),另外你也必須輸入一個(gè)支付密碼(好比token),這有這兩者都符合的情況下,你才能成功進(jìn)入賬號(hào)付款。   

看下面一段代碼:

<?php  

session_start();  

$token = 'SHIFLETT' . $_SERVER['HTTP_USER_AGENT']; 

$_SESSION['token'] = md5($token . session_id());  

?> 

注意:Accept這個(gè)頭部不應(yīng)該被用來(lái)生成token,因?yàn)橛行g覽器會(huì)自動(dòng)改變這個(gè)頭部,當(dāng)用戶刷新瀏覽器的時(shí)候。 

在你的驗(yàn)證機(jī)制中加入了這個(gè)非常難于猜測(cè)出來(lái)的token以后,安全性會(huì)得到很大的提升。假如這個(gè)token通過(guò)像session id一樣的方式來(lái)進(jìn)行傳遞,這種情況下,一個(gè)攻擊者必須完成必要的3步來(lái)劫持用戶的session:

獲取一個(gè)合法的session ID

在請(qǐng)求中加入相同的User-Agent頭部,用與生成token

在請(qǐng)求中攜帶被攻擊者的token

這里面有個(gè)問(wèn)題。如果session id以及token都是通過(guò)GET數(shù)據(jù)來(lái)傳遞的話,那么對(duì)于能獲取session ID的攻擊者,同樣就能夠獲取到這個(gè)token。所以,比較安全靠譜的方式應(yīng)該是利用兩種不同的數(shù)據(jù)傳遞方式來(lái)分別傳遞session id以及token。例如,通過(guò)cookie來(lái)傳遞session id,然后通過(guò)GET數(shù)據(jù)來(lái)傳遞token。因此,假如攻擊者通過(guò)某種手段獲得了這個(gè)唯一的用戶身份標(biāo)識(shí),也是不太可能同時(shí)輕松地獲取到這個(gè)token,它相對(duì)來(lái)說(shuō)依然是安全的。

還有很多的技術(shù)手段可以用來(lái)加強(qiáng)你的session機(jī)制的安全性。希望你在大致了解session的內(nèi)部本質(zhì)以后,可以設(shè)計(jì)出適合你的應(yīng)用系統(tǒng)的驗(yàn)證機(jī)制,從而大大的提高系統(tǒng)的安全性。畢竟,你是最熟悉當(dāng)下你開發(fā)的系統(tǒng)的開發(fā)者之一,可以根據(jù)實(shí)際情況來(lái)實(shí)施一些特有的,額外的安全措施。

 

總結(jié)

以上只是大概地描述了session的工作機(jī)制,以及簡(jiǎn)單地闡述了一些安全措施。但要記住,以上的方法都是能夠加強(qiáng)安全性,不是說(shuō)能夠完全保護(hù)你的系統(tǒng),希望讀者自己再去調(diào)研相關(guān)內(nèi)容。在這個(gè)調(diào)研過(guò)程中,相信你會(huì)學(xué)到很有實(shí)際使用價(jià)值的方案。


提交成功!非常感謝您的反饋,我們會(huì)繼續(xù)努力做到更好!

這條文檔是否有幫助解決問(wèn)題?

非常抱歉未能幫助到您。為了給您提供更好的服務(wù),我們很需要您進(jìn)一步的反饋信息:

在文檔使用中是否遇到以下問(wèn)題: