使用 Cookie 實(shí)現(xiàn)公有云會(huì)話跟蹤

問題描述

軟件即服務(wù) (Software as a Service) 公有云平臺(tái)運(yùn)營商提供各種各樣的服務(wù),用戶可以根據(jù)自己的需要選擇相應(yīng)的服務(wù)。當(dāng)用戶需要某一種服務(wù)時(shí),需要登陸服務(wù)提供商的網(wǎng)站,創(chuàng)建這一服務(wù)的一個(gè)實(shí)例(instance)來作為服務(wù)實(shí)體。與此同時(shí),服務(wù)提供商會(huì)為這個(gè)實(shí)例創(chuàng)建一個(gè)憑證(credential)作為其他 SDK 方式連接的憑證。同一用戶可以擁有多個(gè)實(shí)例來作為不同服務(wù)的實(shí)體。用戶登錄以后,客戶端存儲(chǔ)了服務(wù)器端生成的特定 Cookie 做為身份認(rèn)證。網(wǎng)站認(rèn)證大多采用單點(diǎn)登錄(Single Sign On,簡稱 SSO)技術(shù),而特定的網(wǎng)站存儲(chǔ)在同一瀏覽器的身份 Cookie 只有一份。如果同一用戶在同一個(gè)瀏覽器的多個(gè) Tab 下操作不同的實(shí)例,那么服務(wù)器端無法區(qū)分請求的主體是哪一個(gè)實(shí)例,從而導(dǎo)致兩個(gè)實(shí)例的操作在服務(wù)器端混為一起。

解決思路

由于 Cookie 在同一瀏覽器中是共享的,所以服務(wù)器端無法通過 Cookie 區(qū)分不同 Tab 中的會(huì)話。而且,前端頁面無法用腳本的方式獲取瀏覽器 Tab 標(biāo)識(shí)。因此,要跟蹤 Tab 級別會(huì)話,就需要一個(gè)能在 Tab 級別跟蹤會(huì)話的令牌(Token)保存于 Cookie 中。

Cookie 在客戶端以鍵值對(Key-Value)的形式來存儲(chǔ),一個(gè) Cookie 就是一對 Key-Value。通常經(jīng)過身份驗(yàn)證之后,Web 網(wǎng)站為會(huì)話生成一個(gè)固定 Key 的 Cookie,并存儲(chǔ)在客戶端。客戶端在發(fā)起新的請求時(shí)將此 Cookie 一并傳送給服務(wù)器端用于身份識(shí)別。

為了徹底的分離多 Tab 下的會(huì)話,在服務(wù)器端生成會(huì)話的時(shí)候,可以為每一個(gè)瀏覽器 Tab 生成一個(gè)不同 Key 的 Cookie,并將此 Key 記錄在返回的 HTML 頁面中。HTML 頁面是 Tab 隔離的。此客戶端向服務(wù)器發(fā)起新的請求時(shí),客戶端將預(yù)存在 HTML 中的 Key 傳給服務(wù)器端。服務(wù)器端獲取到客戶端傳遞的 Key 值之后,就可以獲取到對應(yīng)的身份 Cookie。

本文將綜合多種會(huì)話跟蹤技術(shù)解決不同 Tab 之間跟蹤不同會(huì)話的問題。

會(huì)話跟蹤技術(shù)

會(huì)話跟蹤是 Web 應(yīng)用的基礎(chǔ)技術(shù)之一。目前主流的會(huì)話跟蹤技術(shù)有以下四種:

  1. URL 重寫:URL 是互聯(lián)網(wǎng)統(tǒng)一資源定位符。URL 重寫的技術(shù)是將一段附加數(shù)據(jù)添加到 URL 的路徑上。通常附加數(shù)據(jù)包含會(huì)話 ID。會(huì)話 ID 是服務(wù)器端存儲(chǔ)特定會(huì)話對象的標(biāo)識(shí)。
  2. 隱藏表單****域:將會(huì)話的 ID 存儲(chǔ)在表單的隱藏元素中。用戶提交表單時(shí),會(huì)話的 ID 一起被提交到服務(wù)器端。
  3. Cookie:Cookie 是以鍵值對的結(jié)構(gòu)存儲(chǔ)在瀏覽器端的一段文本信息。服務(wù)器端可以將特定的信息,例如會(huì)話 ID,包含在用戶請求的響應(yīng)中返回給瀏覽器端。在新的請求中,瀏覽器會(huì)自動(dòng)攜帶存儲(chǔ)的 Cookie 提交到服務(wù)器端。
  4. Session:HTTP 協(xié)議是無狀態(tài)的,同一系統(tǒng)的不同資源只允許有對應(yīng)權(quán)限的用戶訪問。用戶登錄之后,客戶端和服務(wù)器端需要維持會(huì)話。通常服務(wù)器端會(huì)提供會(huì)話管理的機(jī)制,將不同客戶的身份信息存儲(chǔ)在不同的區(qū)域。瀏覽器向服務(wù)器發(fā)起請求時(shí),需要提供會(huì)話 ID,這樣服務(wù)器端就可以獲取到對應(yīng)客戶端的身份,返回請求的資源。

在本問題的解決方案中同時(shí)使用了以上四種技術(shù)。

實(shí)現(xiàn)過程

目前瀏覽器無法提供區(qū)分 Tab 的方法,即無法使用瀏覽器端接口獲取到 Tab 的標(biāo)識(shí)。Web 網(wǎng)站使用 SSO 的技術(shù),服務(wù)器在認(rèn)證用戶的身份之后,通常會(huì)給客戶端返回一個(gè)固定 Key 值、用于身份識(shí)別的 Cookie (此處涉及到會(huì)話跟蹤技術(shù)三)。在此瀏覽器后續(xù)的請求中,客戶端(瀏覽器)會(huì)將此 Cookie 提供給服務(wù)器端用于身份識(shí)別,如圖 1 所示。由此可見,無論是客戶端還是服務(wù)器端都未曾考慮同一賬戶多 Tab 下的不同會(huì)話的跟蹤問題。

圖 1. 固定 Cookie Key 認(rèn)證過程
image

解決這個(gè)問題首先需要使用不同的 Key 作為身份標(biāo)識(shí)提供給客戶端。過去 SSO 產(chǎn)生的 Token 存儲(chǔ)在客戶端類似于這樣的格式 AUTH=xyz。其中 AUTH 是 Key,xyz 是 Value。由于這是身份認(rèn)證的信息,Value 一般是加密存儲(chǔ)的,防止惡意盜取會(huì)話信息。

為了識(shí)別不同 Tab 下的會(huì)話,新的 Token 存儲(chǔ)的方式需要不同的 Key,例如:AUTH-456784567345=xyzAUTH 是這個(gè)身份認(rèn)證 Cookie 標(biāo)識(shí)的前綴,而數(shù)字串 456784567345 則是服務(wù)器端隨機(jī)生成的一個(gè) Long 型數(shù)字作為后綴,用來區(qū)分 Tab 身份。

如果用戶在三個(gè) Tab 下對同一個(gè)網(wǎng)站登錄了不同的身份,那么會(huì)出現(xiàn)三個(gè) Token,而過去只有一個(gè)。那么在任何一個(gè) Tab 下操作,請求發(fā)送到服務(wù)器端的時(shí)候,客戶端都會(huì)將此三個(gè) Token 帶到請求里,服務(wù)器需要知道到底哪一個(gè) Key 才是當(dāng)前 Tab 的身份信息,如圖 2 所示:

圖 2. 可變后綴 Cookie Key 的認(rèn)證過程
image

因此,客戶端需求在發(fā)送請求的時(shí)候告訴服務(wù)器端身份標(biāo)識(shí)的后綴。完成登錄認(rèn)證的時(shí)候,服務(wù)器端返回給客戶端主頁面的時(shí)候,服務(wù)器端可以將此后綴隱藏在某個(gè)子頁面中(HTML 代碼是 Tab 隔離的,此處涉及到會(huì)話跟蹤技術(shù)二)。代碼如:<input type="hiden" name="auth-suffix" id="suffix" value="" />。此子頁面一直存在于會(huì)話登錄中,例如網(wǎng)頁的導(dǎo)航欄。大多數(shù)的客戶端請求有兩種,一種是 GET 請求,一類是 POST 請求:

  • 對于 GET 請求,需要客戶端腳本將請求的 URL 后添加后綴的參數(shù)(此處涉及到會(huì)話跟蹤技術(shù)一),例如:https://www.hostname.com/app?suffix=456784567345
  • 對于 POST 請求,可以將后綴放在 POST 請求的 Parameter 參數(shù)里。JQuery 代碼:params={"suffix": "456784567345"}; $.ajax({type:"POST", url:https://hostname/url, data:params, datatype:"json", success:()=>{}});

如此一來,服務(wù)器端就可以獲取瀏覽器某個(gè) Tab 的后綴,近而取得相應(yīng)的 Cookie 來獲取這一 Tab 的身份信息了。

為了提高安全性,此實(shí)現(xiàn)方式還需要服務(wù)器端實(shí)現(xiàn)會(huì)話管理(此處涉及到會(huì)話跟蹤技術(shù)四)。

如果會(huì)話管理服務(wù)器只有一個(gè)節(jié)點(diǎn),可以使用簡單的 Map 進(jìn)行管理。Map 的 Key 是 Session ID,Map 的 Value 是 Session 對象。首先,服務(wù)器端從瀏覽器端提交的請求中獲取 Cookie 的后綴參數(shù)值,進(jìn)而得到 Cookie 的 Key (固定前綴+后綴)。由于 Cookie 的存儲(chǔ)結(jié)構(gòu)也是 Map,服務(wù)器端即可獲取到對應(yīng) Cookie 的 Value。解密之后,得到 Cookie 中存儲(chǔ)的服務(wù)器端 Session ID。服務(wù)器端通過 Session ID 獲取到 Session 對象,得到存儲(chǔ)在 Session 對象中的用戶信息。

如果會(huì)話管理服務(wù)器是集群的組織結(jié)構(gòu),那么可以采用支持集群的 Redis 等框架實(shí)現(xiàn)服務(wù)器會(huì)話管理服務(wù)。如果讀者對 Redis 技術(shù)有興趣,可自行查閱相關(guān)文章資料,本文不再詳述。

總結(jié)

大部分的網(wǎng)站并沒有支持 Tab 級會(huì)話跟蹤。然而這一技術(shù)在公有云的普及下,變得越來越重要。雖然用戶可以通過啟動(dòng)多瀏覽器的進(jìn)程來規(guī)避此問題,但是多瀏覽器的操作也會(huì)給用戶帶來需要切換瀏覽器和耗費(fèi)更多的計(jì)算機(jī)資源的弊端。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 1. cookie 1.1 什么是cookie cookie 是存儲(chǔ)于訪問者的計(jì)算機(jī)中的變量。每當(dāng)同一臺(tái)計(jì)算機(jī)通過...
    cbw100閱讀 4,192評論 0 13
  • 作者:晚晴幽草軒www.jeffjade.com/2016/10/31/115-summary-of-cookie...
    饑人谷_Dylan閱讀 1,261評論 0 51
  • 背景在HTTP協(xié)議的定義中,采用了一種機(jī)制來記錄客戶端和服務(wù)器端交互的信息,這種機(jī)制被稱為cookie,cooki...
    時(shí)芥藍(lán)閱讀 2,461評論 1 17
  • 鄉(xiāng)間的夜,原本深邃而寧靜,確因知了的存在,而多了一份繁華。 睡夢中被清脆的叫聲吵醒,而后思緒萬千,...
    懶散的小七閱讀 318評論 0 1
  • 今天,是我在這里工作的最后一天。 好好珍惜,和孩子們一起快樂的時(shí)光。 今早起床還是很晚,本來鬧鐘已經(jīng)將我鬧醒,竟然...
    竹子在心閱讀 237評論 0 2

友情鏈接更多精彩內(nèi)容