使用PHP編寫用戶登錄的代碼時(shí),通常會涉及HTML表單來接收用戶名和密碼,然后使用PHP來處理這些輸入并驗(yàn)證它們。以下是一個簡單的PHP用戶登錄示例,其中假設(shè)你已經(jīng)有了一個存儲用戶信息的MySQL數(shù)據(jù)庫。
首先,你需要一個HTML表單(`login.html`):
```
于Cookie和Session的功能與工作原理,在這里我就不再敘述了,大家想要了解可以看一下我的上一篇博客,講的還是很細(xì)致的。
但是之前講的Session是運(yùn)行在一臺服務(wù)器上的,所有的訪問都會到達(dá)我們的唯一服務(wù)器上,這樣我們可以根據(jù)客戶端傳來的sessionID,來獲取session,或在對應(yīng)Session不存在的情況下(session 生命周期到了/用戶第一次登錄),創(chuàng)建一個新的Session;但是,如果我們在集群環(huán)境下,假設(shè)我們有兩臺服務(wù)器A,B,用戶的請求會由Nginx服務(wù)器進(jìn)行轉(zhuǎn)發(fā)(別的方案也是同理),用戶登錄時(shí),Nginx將請求轉(zhuǎn)發(fā)至服務(wù)器A上,A創(chuàng)建了新的session,并將SessionID返回給客戶端,用戶在瀏覽其他頁面時(shí),客戶端驗(yàn)證登錄狀態(tài),Nginx將請求轉(zhuǎn)發(fā)至服務(wù)器B,由于B上并沒有對應(yīng)客戶端發(fā)來sessionId的session,所以會重新創(chuàng)建一個新的session,并且再將這個新的sessionID返回給客戶端,這樣,我們可以想象一下,用戶每一次操作都有1/2的概率進(jìn)行再次的登錄,這樣不僅對用戶體驗(yàn)特別差,還會讓服務(wù)器上的session激增,加大服務(wù)器的運(yùn)行壓力。
為了解決集群環(huán)境下的seesion共享問題,共有4種解決方案:
1.粘性session
粘性session是指Ngnix每次都將同一用戶的所有請求轉(zhuǎn)發(fā)至同一臺服務(wù)器上,即將用戶與服務(wù)器綁定。
2.服務(wù)器session復(fù)制
即每次session發(fā)生變化時(shí),創(chuàng)建或者修改,就廣播給所有集群中的服務(wù)器,使所有的服務(wù)器上的session相同。
3.session共享
緩存session,使用redis, memcached。
4.session持久化
將session存儲至數(shù)據(jù)庫中,像操作數(shù)據(jù)一樣才做session。
其實(shí),最簡單的兩種方案,就是方案一和方案三,都不需要對session進(jìn)行任何操作,只需要將Nginx和Tomcat上的配置文件修改一下即可。由于我們做集群,訪問量一定是比較大的了,對于第一種方案,如果某臺服務(wù)器發(fā)生故障,此服務(wù)器上的所有用戶的session都會丟失,所以今天我們采用第三種解決方案。
感謝開源項(xiàng)目tomcat-redis-session-manager,感謝項(xiàng)目的發(fā)起者jcoleman。
此方案最簡單之處就在于我們無需修改項(xiàng)目,只需要修改Tomcat的context.xml配置文件即可,并且,redis服務(wù)器同樣可以做分布式。
接下來,我們來講解一下如何配置tomcat,首先,講解一下注意事項(xiàng),因?yàn)轫?xiàng)目的原因,并沒能用maven來管理依賴的包,而在我配置的時(shí)候,很正常的發(fā)生了包版本間的沖突,從redis中取出的序列化后的session無法轉(zhuǎn)換為HttpSession,所以,大家做的時(shí)候一定要注意版本間的兼容問題。
把我使用的版本給大家做個參考吧,tomcat-redis-session-manager-1.1.jar,jedis-2.1.0.jar,commons-pool-1.6.jar
這三個包需放入 tomcat的安裝目錄下的lib文件夾下,IDE自帶的tomcat可以在配置中查看。
需注意的是,當(dāng)redis的版本‘過高’時(shí),需要依賴commons-pool2.jar,(具體版本不寫)。
接下來,我們就講一下最核心的配置,配置context.xml文件(文件路徑workspace\.metadata\.me_tcat7\conf,此處僅是myeclipse編輯器的路徑)
[html] view plain copy
這個里的class路徑具體看tomcat-redis-session-manager里的路徑。
可能你會遇到重啟tomcat配置文件會被還原的問題,那么你還需要修改另一處的context.xml文件,workspace\Servers\MyEclipse Tomcat v7.0-config文件夾中的,修改內(nèi)容同上。
接下來,給大家看一下配置完成后的結(jié)果:
圖1為監(jiān)聽到的redis服務(wù)器的狀態(tài),可以看到我們將session序列化后以sessionID為key存入了redis中,圖2可以看到是客戶端header中的cookie信息(若有疑問可以查看我上一篇的博客),圖三是我在redis客戶端get key為sessionID的記錄,可以驗(yàn)證成功,我們配置是成功了的,因?yàn)槭褂玫淖约旱碾娔X,配置有限,并沒有開幾個tomcat來測試,不過上述還是很有說服力的(線上已經(jīng)測試過了)。
希望對你有幫助!
ookie 和 Session 是 Web 應(yīng)用程序中用于保持用戶狀態(tài)的兩種常見機(jī)制,它們之間既有聯(lián)系也有區(qū)別。
Cookie 是由服務(wù)器在 HTTP 響應(yīng)中發(fā)送給客戶端(通常是瀏覽器)的一小段數(shù)據(jù)。客戶端將這些信息保存在本地,并在后續(xù)的請求中自動將其發(fā)送回服務(wù)器。
而 Session 是在服務(wù)器端創(chuàng)建的一種機(jī)制,用于跟蹤用戶的會話狀態(tài)。服務(wù)器會給每個用戶分配一個唯一的會話 ID,并將該 ID 通過 Cookie 或其他方式傳遞給客戶端。客戶端隨后在請求時(shí)攜帶會話 ID,服務(wù)器根據(jù)這個 ID 從內(nèi)存或數(shù)據(jù)庫中檢索與該用戶相關(guān)的會話數(shù)據(jù)。
嚴(yán)格意義上來說,Cookie 和 Session 是沒有任何關(guān)系的,但 Session 的實(shí)現(xiàn)中借助了 Cookie 機(jī)制。
通過以下 Session 執(zhí)行的機(jī)制,我們就能知道 Session 是如何借助 Cookie 完成自己的執(zhí)行流程的:
所以默認(rèn)情況下,Session 是借助 Cookie 來完成身份標(biāo)識的傳遞的,這樣服務(wù)器端才能根據(jù) Session ID 和保存的會話信息進(jìn)行關(guān)聯(lián),用于找到某個具體登錄的用戶,所以說:默認(rèn)情況下,Session 機(jī)制是依賴 Cookie 實(shí)現(xiàn)的。
那么問題來了,禁用 Cookie 后 Session 還能用嗎?
答案是:默認(rèn)情況下禁用 Cookie 后,Session 是無法正常使用的。
這是因?yàn)榇蠖鄶?shù) Web 服務(wù)器都是依賴于 Cookie 來傳遞 Session 的會話 ID 的。客戶端瀏覽器禁用 Cookie 時(shí),服務(wù)器將無法把會話 ID 發(fā)送給客戶端,客戶端也無法在后續(xù)請求中攜帶會話 ID 返回給服務(wù)器,從而導(dǎo)致服務(wù)器無法識別用戶會話。
但是,默認(rèn)情況下禁用 Cookie 后,Session 就不能用了,但可以通過一些手段來解決這個問題。
以下的兩種解決方案可以繞過 Cookie 繼續(xù)運(yùn)行 Session:
這些方法雖然可以在禁用 Cookie 的情況下繼續(xù)使用 Session,但需要在服務(wù)器端進(jìn)行相應(yīng)的代碼修改和配置。但同時(shí)這些手段也帶來了以下幾個新問題:
Session 實(shí)現(xiàn)是依賴 Cookie 來存儲會話 ID 的,所以默認(rèn)情況下,如果禁用了 Cookie,Session 就不能使用了。但是我們可以通過特殊的手段,例如在 URL 中傳遞 SessionID 或表單中使用隱藏字段傳遞 SessionID 的方式,配合服務(wù)器端代碼的修改,是 Session 機(jī)制繼續(xù)使用,但這樣使用增加了編碼的復(fù)雜度,和帶來了一定的安全風(fēng)險(xiǎn)。
本文已收錄到我的面試小站 [www.javacn.site](https://www.javacn.site),其中包含的內(nèi)容有:Redis、JVM、并發(fā)、并發(fā)、MySQL、Spring、Spring MVC、Spring Boot、Spring Cloud、MyBatis、設(shè)計(jì)模式、消息隊(duì)列等模塊。
*請認(rèn)真填寫需求信息,我們會在24小時(shí)內(nèi)與您取得聯(lián)系。