理解Session实现原理及安全运用
##實(shí)現(xiàn)原理##
java的web容器都實(shí)現(xiàn)了session機(jī)制,實(shí)現(xiàn)的邏輯思想都是一致的,但是具體方案可能會存在一定差異,這里我以tomcat容器為例,探討下session實(shí)現(xiàn)的機(jī)制。
下圖是tomcat源碼里session實(shí)現(xiàn):
實(shí)現(xiàn)包的路徑是:org.apache.catalina.session,tomcat對外提供session調(diào)用的接口不在這個(gè)實(shí)現(xiàn)包里,對外接口是在包javax.servlet.http下的HttpSession,而實(shí)現(xiàn)包里的StandardSession是tomcat提供的標(biāo)準(zhǔn)實(shí)現(xiàn),當(dāng)然對外tomcat不希望用戶直接操作StandardSession,而是提供了一個(gè)StandardSessionFacade類,tomcat容器里具體操作session的組件是servlet,而servlet操作session是通過StandardSessionFacade進(jìn)行的,這樣就可以防止程序員直接操作StandardSession所帶來的安全問題。(StandardSessionFacade使用了設(shè)計(jì)模式里的Facade(外觀)模式,外觀模式能讓不同邏輯層的組件進(jìn)行解耦)。
實(shí)現(xiàn)類是有Manager的類是用來管理session的工具類,它負(fù)責(zé)創(chuàng)建和銷毀session對象,其中ManagerBase是所有session管理工具類的基類,它是一個(gè)抽象類,所有具體實(shí)現(xiàn)session管理功能的類都要繼承這個(gè)類,該類有一個(gè)受保護(hù)的方法,該方法就是創(chuàng)建sessionId值的方法(tomcat的session的id值生成的機(jī)制是一個(gè)隨機(jī)數(shù)加時(shí)間加上jvm的id值,jvm的id值會根據(jù)服務(wù)器的硬件信息計(jì)算得來,因此不同jvm的id值都是唯一的),StandardManager類是tomcat容器里默認(rèn)的session管理實(shí)現(xiàn)類,它會將session的信息存儲到web容器所在服務(wù)器的內(nèi)存里。PersistentManagerBase也是繼承ManagerBase類,它是所有持久化存儲session信息的基類,PersistentManager繼承了PersistentManagerBase,但是這個(gè)類只是多了一個(gè)靜態(tài)變量和一個(gè)getName方法,目前看來意義不大,對于持久化存儲session,tomcat還提供了StoreBase的抽象類,它是所有持久化存儲session的基類,另外tomcat還給出了文件存儲FileStore和數(shù)據(jù)存儲JDBCStore兩個(gè)實(shí)現(xiàn)。
##安全運(yùn)用##
###運(yùn)用問題###
由上面所描述的session實(shí)現(xiàn)機(jī)制,我們發(fā)現(xiàn),為了彌補(bǔ)http協(xié)議的無狀態(tài)的特點(diǎn),服務(wù)端會占用一定的內(nèi)存和cpu用來存儲和處理session計(jì)算的開銷,這也就是tomcat這個(gè)的web容器的并發(fā)連接那么低(tomcat官方文檔里默認(rèn)的連接數(shù)是200)原因之一。因此很多java語言編寫的網(wǎng)站,在生產(chǎn)環(huán)境里web容器之前會加一個(gè)靜態(tài)資源服務(wù)器,例如:apache服務(wù)器或nginx服務(wù)器,靜態(tài)資源服務(wù)器沒有解決http無狀態(tài)問題的功能,因此部署靜態(tài)資源的服務(wù)器也就不會讓出內(nèi)存或cpu計(jì)算資源專門去處理像session這樣的功能,這些內(nèi)存和cpu資源可以更有效的處理每個(gè)http請求,因此靜態(tài)資源服務(wù)器的并發(fā)連接數(shù)更高,所以我們可以讓那些沒有狀態(tài)保持要求的請求直接在靜態(tài)服務(wù)器里處理,而要進(jìn)行狀態(tài)保持的請求則在java的web容器里進(jìn)行處理,這樣能更好的提升網(wǎng)站的效率。
當(dāng)下的互聯(lián)網(wǎng)網(wǎng)站為了提高網(wǎng)站安全性和并發(fā)量,服務(wù)端的部署的服務(wù)器的數(shù)量往往是大于或等于兩臺,多臺服務(wù)器對外提供的服務(wù)是等價(jià)的,但是不同的服務(wù)器上面肯定會有不同的web容器,由上面的講述我們知道session的實(shí)現(xiàn)機(jī)制都是web容器里內(nèi)部機(jī)制,這就導(dǎo)致一個(gè)web容器里所生成的session的id值是不同的,因此當(dāng)一個(gè)請求到了A服務(wù)器,瀏覽器得到響應(yīng)后,客戶端存下的是A服務(wù)器上所生成的session的id,當(dāng)在另一個(gè)請求分發(fā)到了B服務(wù)器,B服務(wù)器上的web容器是不能識別這個(gè)session的id值,更不會有這個(gè)sessionID所對應(yīng)記錄下來的信息,這個(gè)時(shí)候就需要兩個(gè)不同web容器之間進(jìn)行session的同步。Tomcat容器有一個(gè)官方的解決方案就是使用apache+tomcat+mod_jk方案,當(dāng)一個(gè)web容器里session的信息發(fā)生變化后,該web容器會向另一個(gè)web容器進(jìn)行廣播,另一個(gè)web收到廣播后將session信息同步到自己的容器里,這個(gè)過程是十分消耗系統(tǒng)資源,當(dāng)訪問量增加會嚴(yán)重影響到網(wǎng)站的效率和穩(wěn)定性。
我現(xiàn)在所做的網(wǎng)站有一個(gè)解決方案,當(dāng)用戶請求網(wǎng)站的時(shí)候會先將請求發(fā)送給硬件的負(fù)載均衡設(shè)備,該設(shè)備可以截獲客戶端發(fā)送過來的session的id值,然后我們根據(jù)這個(gè)id值找到產(chǎn)生這個(gè)session的服務(wù)器,井請求直接發(fā)送給這臺服務(wù)器。這種解決方案看起來解決了session共享問題,其實(shí)結(jié)果是將集群系統(tǒng)最終變回了單點(diǎn)系統(tǒng),如果處理請求的web容器掛掉了,那么用戶的相關(guān)會話操作也就廢掉了。此外,這種做法也干擾了負(fù)載均衡服務(wù)器的負(fù)載均衡的計(jì)算,讓請求的分發(fā)并不是公平的。
一般大型互聯(lián)公司的網(wǎng)站都是有一個(gè)個(gè)獨(dú)立的頻道所組成的,例如我們常用的百度,會有百度搜索,百度音樂,百度百科等等,我相信他們不會把這些不同頻道都給一個(gè)開發(fā)團(tuán)隊(duì)完成,應(yīng)該每個(gè)頻道都是一個(gè)獨(dú)立開發(fā)團(tuán)隊(duì),因?yàn)槊總€(gè)頻道的應(yīng)用的都是獨(dú)立的web應(yīng)用,那么就存在一個(gè)跨站點(diǎn)的session同步的問題,跨站點(diǎn)的登錄可以使用單點(diǎn)登錄的(SSO)的解決方案,但是不管什么解決方案,跨站點(diǎn)的session共享任然是逃避不了的問題。
由上所述,Session一共有兩個(gè)問題需要解決:(1) Session的存儲應(yīng)該獨(dú)立于web容器,也要獨(dú)立于部署web容器的服務(wù)器;(2)如何進(jìn)行高效的Session同步;
在講到解決這些問題之前,我們首先要考慮下session如何存儲才是高效,是存在內(nèi)存、文件還是數(shù)據(jù)庫了?文件和數(shù)據(jù)庫的存儲方式都是將session的數(shù)據(jù)固化到硬盤上,操作硬盤的方式就是IO,IO操作的效率是遠(yuǎn)遠(yuǎn)低于操作內(nèi)存的數(shù)據(jù),因此文件和數(shù)據(jù)庫存儲方式是不可取的,所以將session數(shù)據(jù)存儲到內(nèi)存是最佳的選擇。因此最好的解決方案就是使用分布式緩存技術(shù),例如:memcached和redis,將session信息的存儲獨(dú)立出來也是解決session同步問題的方法。
Tomcat的Session同步也有使用memcache的解決方案,大家可以參加下面的文章: http://blog.sina.com.cn/s/blog_5376c71901017bqx.html
但是該方案只是解決了同步問題,session機(jī)制仍然和web容器緊耦合,我們需要一個(gè)高效、可擴(kuò)展的解決方案,那么我們就應(yīng)該不是簡單的把session獨(dú)立出來存儲而是設(shè)計(jì)一個(gè)完全獨(dú)立的session機(jī)制,它既能給每個(gè)web應(yīng)用提供session的功能又可以實(shí)現(xiàn)session同步,下面是一篇用zookeeper實(shí)現(xiàn)的分布式session方案:
http://www.open-open.com/lib/view/open1378556537303.html
###安全問題###
Http是一種無狀態(tài)性的協(xié)議。這是因?yàn)榇朔N協(xié)議不要求瀏覽器在每次請求中標(biāo)明它自己的身份,并且瀏覽器以及服務(wù)器之間并沒有保持一個(gè)持久性的連接用于多個(gè)頁面之間的訪問。當(dāng)一個(gè)用戶訪問一個(gè)站點(diǎn)的時(shí)候,用戶的瀏覽器發(fā)送一個(gè)http請求到服務(wù)器,服務(wù)器返回給瀏覽器一個(gè)http響應(yīng)。其實(shí)很簡單的一個(gè)概念,客戶端一個(gè)請求,服務(wù)器端一個(gè)回復(fù),這就是整個(gè)基于http協(xié)議的通訊過程。
因?yàn)閣eb應(yīng)用程序是基于http協(xié)議進(jìn)行通訊的,而我們已經(jīng)講過了http是無狀態(tài)的,這就增加了維護(hù)web應(yīng)用程序狀態(tài)的難度, 對于開發(fā)者來說,是一個(gè)不小的挑戰(zhàn)。Cookies是作為http的一個(gè)擴(kuò)展誕生的,其主要用途是彌補(bǔ)http的無狀態(tài)特性,提供了一種保持客戶端與服務(wù)器端之間狀態(tài)的途徑,但是由于出于安全性的考慮,有的用戶在瀏覽器中是禁止掉cookie的。這種情況下,狀態(tài)信息只能通過url中的參數(shù)來傳遞到服務(wù)器端,不過這種方式的安全性很差。事實(shí)上,按照通常的想法,應(yīng)該有客戶端來表明自己的身份,從而和服務(wù)器之間維持一種狀態(tài),但是出于安全性方面的考慮,我們都應(yīng)該明白一點(diǎn) – 來自客戶端的信息都是不能完全信任的。
盡管這樣,針對維持web應(yīng)用程序狀態(tài)的問題,相對來說,還是有比較優(yōu)雅的解決方案的。不過,應(yīng)該說是沒有完美的解決方案的,再好的解決方案也不可能適用所有的情況。這篇文章將介紹一些技術(shù)。這些技術(shù)可以用來比較穩(wěn)定地維持應(yīng)用程序的狀態(tài)以及抵御一些針對session的攻擊,比如會話劫持。并且你可以學(xué)習(xí)到cookie是怎樣工作的,php 的session做了那些事情,以及怎樣才能劫持session。
如何才能保持web應(yīng)用程序的狀態(tài)以及選擇最合適的解決方案呢?在回答這個(gè)問題之前,必須得先了解web的底層協(xié)議 – Hypertext Transfer Protocol (HTTP)。
當(dāng)用戶訪問http://example.com這個(gè)域名的時(shí)候,瀏覽器就會自動和服務(wù)器建立tcp/ip連接,然后發(fā)送http請求到example.com的服務(wù)器的80端口。該個(gè)請求的語法如下所示:
GET / HTTP/1.1 Host: example.org
以上第一行叫做請求行,第二個(gè)參數(shù)(一個(gè)反斜線在這個(gè)例子中)表示所請求資源的路徑。反斜線代表了根目錄;服務(wù)器會轉(zhuǎn)換這個(gè)根目錄為服務(wù)器文件系統(tǒng)中的一個(gè)具體目錄。
第二行描述的是http頭部的語法。在這個(gè)例子中的頭部是Host, 它標(biāo)識了瀏覽器希望獲取資源的域名主機(jī)。還有很多其它的請求頭部可以包含在http請求中,比如user-Agent頭部,在php可以通過$_SERVER['HTTP_USER_AGENT']獲取請求中所攜帶的這個(gè)頭部信息。
但是遺憾的是,在這個(gè)請求例子中,沒有任何信息可以唯一標(biāo)識當(dāng)前這個(gè)發(fā)出請求的客戶端。有些開發(fā)者借助請求中的ip頭部來唯一標(biāo)識發(fā)出此次請求的客戶端,但是這種方式存在很多問題。因?yàn)?#xff0c;有些用戶是通過代理來訪問的,比如用戶A通過代理B連接網(wǎng)站www.example.com, 服務(wù)器端獲取的ip信息是代理B分配給A的ip地址,如果用戶這時(shí)斷開代理,然后再次連接代理的話,它的代理ip地址又再次改變,也就說一個(gè)用戶對應(yīng)了多個(gè)ip地址,這種情況下,服務(wù)器端根據(jù)ip地址來標(biāo)識用戶的話,會認(rèn)為請求是來自不同的用戶,事實(shí)上是同一個(gè)用戶。 還用另外一種情況就是,比如很多用戶是在同一個(gè)局域網(wǎng)里通過路由連接互聯(lián)網(wǎng),然后都訪問www.example.com的話,由于這些用戶共享同一個(gè)外網(wǎng)ip地址,這會導(dǎo)致服務(wù)器認(rèn)為這些用戶是同一個(gè)用戶發(fā)出的請求,因?yàn)樗麄兪莵碜酝粋€(gè)ip地址的訪問。
保持應(yīng)用程序狀態(tài)的第一步就是要知道如何來唯一地標(biāo)識每個(gè)客戶端。因?yàn)橹挥性趆ttp中請求中攜帶的信息才能用來標(biāo)識客戶端,所以在請求中必須包含某種可以用來標(biāo)識客戶端唯一身份的信息。
現(xiàn)在,我們來看下一個(gè)比較常規(guī)的針對session的攻擊:
用戶訪問http://www.example.org,并且登錄。 example.org的服務(wù)器設(shè)置指示客戶端設(shè)置相關(guān)cookie – PHPSESSID=12345 攻擊者這時(shí)訪問http://www.example.org/,并且在請求中攜帶了對應(yīng)的cookie – PHPSESSID=12345 這樣情況下,因?yàn)閑xample.orge的服務(wù)器通過PHPSESSID來辨認(rèn)對應(yīng)的用戶的,所以服務(wù)器錯(cuò)把攻擊者當(dāng)成了合法的用戶。
整個(gè)過程的描述,請看下面的示例圖:
當(dāng)然這種攻擊的方式,前提條件是攻擊者必須通過某種手段固定,劫持或者猜測出某個(gè)合法用戶的PHPSESSID。雖然這看起來難度很高,但是也不是不可能的事情。
有很多技術(shù)可以用來加強(qiáng)Session的安全性,主要思想就是要使驗(yàn)證的過程對于合法用戶來說,越簡單越好,然后對于攻擊者來說,步驟要越復(fù)雜越好。當(dāng)然,這似乎是比較難于平衡的,要根據(jù)你應(yīng)用程序的具體設(shè)計(jì)來做決策。
最簡單的居于HTTP/1.1請求包括請求行以及一些Host的頭部:
GET / HTTP/1.1
Host: example.org
如果客戶端通過PHPSESSID傳遞相關(guān)的session標(biāo)識符,可以將PHPSESSID放在cookie頭部中進(jìn)行傳遞:
GET / HTTP/1.1
Host: example.org
Cookie: PHPSESSID=12345
同樣地,客戶端也可以將session標(biāo)識符放在請求的url中進(jìn)行傳遞。
GET /?PHPSESSID=12345 HTTP/1.1
Host:example.org
當(dāng)然,session標(biāo)識符也可以包含在POST數(shù)據(jù)中,但是這對用戶體驗(yàn)有影響,所以這種方式很少采用。
因?yàn)閬碜訲CP/IP信息也不一定可以完全信任的,所以,對于web開發(fā)者來說,利用TCP/IP中的信息來加強(qiáng)安全性也是不太合適的。 不過,攻擊者也必須提供一個(gè)合法用戶的唯一的標(biāo)識符,才能假扮成合法用戶進(jìn)入系統(tǒng)。因此,看起來唯一能夠有效的保護(hù)系統(tǒng)的措施,就是盡量地隱藏session標(biāo)識符或者使之難于猜測出來。最好就是兩者都能實(shí)施。
PHP會自動生成一個(gè)隨機(jī)的session ID,基本來說是不可能被猜測出來的,所以這方面的安全還是有一定保障的。但是,要防止攻擊者獲取一個(gè)合法的session ID是相當(dāng)困難的,這基本上不是開發(fā)者所能控制的。
事實(shí)上,許多情況下都有可能導(dǎo)致session ID的泄露。 比如說,如果通過GET數(shù)據(jù)來傳遞session ID的話,就有可能暴露這個(gè)敏感的身份信息。因?yàn)?#xff0c;有的用戶可能會將帶有session ID的鏈接緩存,收藏或者發(fā)送在郵件內(nèi)容中。Cookies是一種像相對來說安全一點(diǎn)的機(jī)制,但是用戶是可以在客戶端中禁止掉cookies的!在一些IE的版本中也有比較嚴(yán)重的安全漏洞,比較有名的就是會泄露cookies給一些有安全隱患的邪惡站點(diǎn)。
因此,作為一個(gè)開發(fā)者,可以肯定session ID是不能被猜測出來的,但是還是有可能被攻擊者使用某些方法獲取到。所以,必須采取一些額外的安全措施來防止此類情況在你的應(yīng)用程序中發(fā)生。
實(shí)際上,一個(gè)標(biāo)準(zhǔn)的HTTP請求中除了Host等必須包含的頭部,還包含了一些可選的頭部.舉一個(gè)例子,看下面的一個(gè)請求:
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
Accept-Language: en
我們可以看到,在以上的一個(gè)請求例子中包含了四個(gè)額外的頭部,分別是User-Agent, Accept, Accept-Charset以及Accept-Language。因?yàn)檫@些頭部不是必須的,所以完全依賴他們在你的應(yīng)用程序中發(fā)揮作用是不太明智的。但是,如果一個(gè)用戶的瀏覽器確實(shí)發(fā)送了這些頭部到服務(wù)器,那么可以肯定的是在接下來的同一個(gè)用戶通過同一個(gè)瀏覽器發(fā)送的請求中,必然也會攜帶這些頭部。當(dāng)然,這其中也會有極少數(shù)的特殊情況發(fā)生。假如以上例子是由一個(gè)當(dāng)前的跟服務(wù)器建立了會話的用戶發(fā)出的請求,考慮下面的一個(gè)請求:
GET / HTTP/1.1 Host:example.org
Cookie:PHPSESSID=12345
User-Agent: Mozilla/5.0
因?yàn)橛邢嗤膕ession id包含在請求的Cookie頭部中,所以相同的php session將會被訪問到。但是,請求里的User-Agent頭部跟先前的請求中的信息是不同的,系統(tǒng)是否可以假定這兩個(gè)請求是同一個(gè)用戶發(fā)出的?
像這種情況下,發(fā)現(xiàn)瀏覽器的頭部改變了,但是不能肯定這是否是一次來自攻擊者的請求的話,比較好的措施就是彈出一個(gè)要求輸入密碼的輸入框讓用戶輸入,這樣的話,對用戶體驗(yàn)的影響不會很大,又能很有效地防止攻擊。
當(dāng)然,你可以在系統(tǒng)中加入核查User-Agent頭部的代碼,類似PHP代碼:
<?php session_start(); if(md5($_SERVER['HTTP_USER_AGENT']) != $_SESSION['HTTP_USER_AGENT']) { /* 彈出密碼輸入框*/ exit; } ?>當(dāng)然,你先必須在第一次請求時(shí),初始化session的時(shí)候,用MD5算法加密user agent信息并且保存在session中,類似PHP代碼:
<?php session_start(); $_SESSION['HTTP_USER_AGENT'] = md5($_SERVER['HTTP_USER_AGENT']); ?>雖然不一定需要用MD5來加密這個(gè)User-Agent信息,但使用這種方式以后就不需要再過濾這個(gè)$_SERVER['HTTP_USER_AGENT']數(shù)據(jù)了。不然的話,在使用這個(gè)數(shù)據(jù)以前必須要進(jìn)行數(shù)據(jù)過濾,因?yàn)槿魏蝸碜钥蛻舳说臄?shù)據(jù)都是不可信任的,必須要注意這一點(diǎn)。
在你檢查這個(gè)User-Agent客戶端頭部信息以后,做為一個(gè)攻擊者必須要完成兩步才能劫持一個(gè)session:
獲取一個(gè)合法的session id包含一個(gè)相同的User-Agent頭部在偽造的請求中
你可能會說,居然攻擊者能獲得有效的session id,那么以他的水平,偽造一個(gè)相同的User-Agent不是件難事。不錯(cuò),但是我們可以說這至少給他添加了一些麻煩,在一定程度上也增加了session機(jī)制的安全性。
你應(yīng)該也能想到了,既然我們可以檢查User-Agent這個(gè)頭部來加強(qiáng)安全性,那么不妨再利用其它的一些頭部信息,把他們組合起來生成一個(gè)加密的token,并且讓客戶端在后續(xù)的請求中攜帶這個(gè)token!這樣的話,攻擊者基本上不可能猜測出這樣一個(gè)token是怎么生成出來的。這好比你用信用卡在超市付款,一個(gè)你必須有信用卡(好比session id),另外你也必須輸入一個(gè)支付密碼(好比token),這有這兩者都符合的情況下,你才能成功進(jìn)入賬號付款。 看下面一段代碼:
<?php session_start(); $token='SHIFLETT' . $_SERVER['HTTP_USER_AGENT']; $_SESSION['token'] = md5($token, session_id()); ?>注意:Accept這個(gè)頭部不應(yīng)該被用來生成token,因?yàn)橛行g覽器會自動改變這個(gè)頭部,當(dāng)用戶刷新瀏覽器的時(shí)候。
在你的驗(yàn)證機(jī)制中加入了這個(gè)非常難于猜測出來的token以后,安全性會得到很大的提升。假如這個(gè)token通過像session id一樣的方式來進(jìn)行傳遞,這種情況下,一個(gè)攻擊者必須完成必要的3步來劫持用戶的session:
獲取一個(gè)合法的session ID 在請求中加入相同的User-Agent頭部,用與生成token 在請求中攜帶被攻擊者的token
這里面有個(gè)問題。如果session id以及token都是通過GET數(shù)據(jù)來傳遞的話,那么對于能獲取session ID的攻擊者,同樣就能夠獲取到這個(gè)token。所以,比較安全靠譜的方式應(yīng)該是利用兩種不同的數(shù)據(jù)傳遞方式來分別傳遞session id以及token。例如,通過cookie來傳遞session id,然后通過GET數(shù)據(jù)來傳遞token。因此,假如攻擊者通過某種手段獲得了這個(gè)唯一的用戶身份標(biāo)識,也是不太可能同時(shí)輕松地獲取到這個(gè)token,它相對來說依然是安全的。
還有很多的技術(shù)手段可以用來加強(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í)際情況來實(shí)施一些特有的,額外的安全措施。
以上只是大概地描述了session的工作機(jī)制,以及簡單地闡述了一些安全措施。但要記住,以上的方法都是能夠加強(qiáng)安全性,不是說能夠完全保護(hù)你的系統(tǒng),希望讀者自己再去調(diào)研相關(guān)內(nèi)容。在這個(gè)調(diào)研過程中,相信你會學(xué)到很有實(shí)際使用價(jià)值的方案。
?
創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎勵(lì)來咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎總結(jié)
以上是生活随笔為你收集整理的理解Session实现原理及安全运用的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: linux--GD库安装
- 下一篇: session_unset()和sess