問題描述
在開發(fā)環(huán)境中,皓優(yōu)企后臺(tái)管理系統(tǒng)的前端服務(wù)器地址為:http://192.168.1.39:8001/dist/ ,后端接口地址http://192.168.1.230:81/managment。在Chrome瀏覽器中輸入輸入http://192.168.1.39:8001/dist/即會(huì)進(jìn)入登錄頁面。在登錄頁面輸入合法的用戶名和密碼以及正確的驗(yàn)證碼,登錄頁反復(fù)提示“驗(yàn)證碼錯(cuò)誤”。該問題在360瀏覽器和firefox瀏覽器上都沒有,目前只在Chrome瀏覽器上出現(xiàn)。
問題分析
打開Chrome開發(fā)者工具,在network欄目中查看請(qǐng)求和響應(yīng)參數(shù)??梢钥吹巾憫?yīng)頭中有set-cookie項(xiàng),比如:Set-Cookie: JSESSIONID=EF8C88B741473AC36CE395668FCBB7B4。同一個(gè)頁面的多個(gè)請(qǐng)求,返回的JSESSIONID都不一樣。這個(gè)值很關(guān)鍵,一個(gè)新的JSESSIONID意味著服務(wù)器又產(chǎn)生一個(gè)新的會(huì)話。通常來說,一個(gè)頁面只產(chǎn)生一個(gè)會(huì)話,之后所有該頁面的請(qǐng)求都是基于該會(huì)話進(jìn)行,關(guān)閉該頁面即代表會(huì)話結(jié)束。這里一個(gè)頁面產(chǎn)了多個(gè)會(huì)話顯然是有問題的。
cookie如何維持會(huì)話狀態(tài)
cookie會(huì)在每次請(qǐng)求時(shí)帶入到請(qǐng)求頭中,服務(wù)器可以通過相關(guān)接口讀取cookie信息,每個(gè)客戶端都有自己的cookie。當(dāng)初次請(qǐng)求服務(wù)器時(shí),cookie為空,服務(wù)器給它分配一個(gè)新的會(huì)話,并將會(huì)話通過Set-Cookie:JSESSIONID=EF8C88B741473AC36CE395668FCBB7B4寫入到cookie。需要注意的是,這里的Set-Cookie并沒有對(duì)cookie直接寫入,而是將Set-Cookie作為響應(yīng)頭返回到客戶端,客戶端得到響應(yīng)后讀取Set-Cookie的內(nèi)容,并將其寫入本地cookie中。再次發(fā)送請(qǐng)求時(shí),新寫入的JSESSIONID會(huì)隨著cookie一同提交到服務(wù)器,服務(wù)器根據(jù)JSESSIONID來查找會(huì)話。如果已經(jīng)存在,則找到原來的會(huì)話,在該會(huì)話的基礎(chǔ)上進(jìn)行通信,否則就重新創(chuàng)建會(huì)話,并再次向客戶返回Set-Cookie及JSESSIONID。如此重復(fù)上述過程,即為cookie維持會(huì)話狀態(tài)的過程。
cookie設(shè)置失敗的原因
具體到皓優(yōu)企后臺(tái)登錄失敗的情況中,服務(wù)端每次處理請(qǐng)求時(shí)都創(chuàng)建新的Session并向客戶端發(fā)送了Set-Cookie。由此可以判斷,客戶端發(fā)送的請(qǐng)求中,Cookie的內(nèi)容要么是不帶JSESSIONID,要么是帶的JSESSIONID在服務(wù)端已經(jīng)失效。在Chrome開發(fā)者工具欄中,打開Application欄,可以看到Cookie的內(nèi)容為空。也就是說,雖然服務(wù)端通過Set-Cookie返回了JSESSIONID,但客戶端并沒有將JSESSIONID寫入到Cookie中。之后的所有請(qǐng)求都不帶JSESSIONID,因此才會(huì)每次請(qǐng)求都產(chǎn)生新的會(huì)話。Set-Cookie是http協(xié)議的約定,為什么會(huì)設(shè)置失敗呢?在Cookie的屬性中,有一個(gè)domain屬性,該屬性記錄了服務(wù)端域名。在皓優(yōu)企后臺(tái)頁面中,cookie設(shè)置的domain域名為http://192.168.1.39:8001/dist/,而響應(yīng)頭中Set-Cookie的domain指向http://192.168.1.230:81/managment。兩者不一致,造成了Set-Cookie無法寫入本地Cookie,從而造成服務(wù)器每次請(qǐng)求都重新分配JSESSIONID,進(jìn)而導(dǎo)致登錄失敗。
解決辦法
打開Chrome瀏覽器,地址欄里輸入:chrome://flags/
找到下面列表項(xiàng)目:
**1 .SameSite by default cookies,
- Cookies without SameSite must be secure**
將這兩項(xiàng)設(shè)置成disabled,然后重啟一下瀏覽器。再次登錄,就能夠成功登錄,并且cookie中也成功寫入了JSESSIONID。一切恢復(fù)正常!