問題
使用者進入頁面A,在頁面A上要執行一個操作X。操作X需要使用者登入後才能訪問,因此係統引導使用者到登入頁,使用者登入後在讓使用者繼續執行操作X。
分析
操作X存在兩種情況,1:跳轉到一個頁面B;2:執行一個操作。
進入頁面B的情況,要在頁面B的入口位置判斷是否使用者是否為登入狀態,是則進入,否則進入登入頁面,登入成功後再進入頁面B。假設頁面A的URL是是url-a,頁面B的url是url-b,登入頁面的url是url-l,那麼瀏覽器的地址依次是url-a,url-b,url-l,url-b。因此,系統就是要解決登入模版如何記錄url-b,並在成功後進入url-b。
執行一個操作的情況。執行操作前判斷使用者的登入狀態,是則執行操作,否則先跳轉到登入頁面,登入成功後返回頁面A,頁面A繼續執行之前的操作。這時,登入頁要記錄頁面A,登入成功後返回A,頁面A要記錄使用者的操作和引數,從登入頁返回後繼續執行。
實現
頁面跳轉
頁面跳轉的情況,由頁面B負責判斷是否要跳轉到登入頁,如果需要用redirect的方式完成。
header("Location: $loginURL");
exit;
在login頁面需要知道是從哪個頁面跳轉來,並儲存,這樣登入成功後再跳轉回原來的頁面。PHP中可以通過$_SERVER[`HTTP_REFERER`]獲得是從哪個頁面進入的的登入頁。
$referer = $_SERVER[`HTTP_REFERER`];
進入登入頁時獲得的$referer必須要記錄下來,才能在登入成功後跳轉回之前的頁面。跨呼叫儲存資訊有4種方式:1、儲存在session中;2、儲存在cookie中;3、作為引數放在url中;4、生成頁面時,作為頁面的隱藏資訊。
放在session中,只能通過php獲取,因此,登入成功後跳轉回原頁面的操作只能在php中進行,這樣就不能實現通過一個ajax呼叫驗證使用者登入資訊後,在前端頁面直接跳轉指定頁面。
採用cookie的方式需要前後端共同確定一個約定,用什麼代表頁面的跳轉資訊,另外前端需要增加cookie的處理邏輯。這種方式可以同時支援前端或後端進行跳轉。
作為引數放在url中可以實現在前端進行跳轉,但是會導致url看起來有些怪異,同時還需要考慮url編碼的問題。
直接生成在登入頁面中(利用頁面模版)作為前端引數,這種方式支援在前端進行跳轉,需要前後端約定引數的定義。
執行操作
執行操作的情況應該是頁面A判斷使用者是否已經登入,或者根據執行操作X的返回結果,由頁面A直接跳轉到登入頁面,登入介面記錄是從哪個頁面跳轉來的。
header("Location: $loginURL");
exit;
頁面A執行跳轉到登入頁面前,首先記錄要執行的操作,例如:操作的名稱,這個資訊必須可以跨請求訪問。操作的相關資訊可以通過url、session、cookie傳遞,或者通過localStorage、sessionStorage保留在客戶端。
如果用url指定要執行的操作(用history.pushState替換url),只能攜帶簡單的引數(放在history中是個好方法?沒想明白),通用性不好。session和cookie需要向伺服器端傳資料,而且獲取保留的引數並不方便。最後決定選擇sessionStorage儲存要執行的方法。
跳轉到登入介面前儲存要執行的操作:
if (window.sessionStorage) {
var method = JSON.stringify({
name: `要執行的方法的名稱`,
args: [引數1,引數2]
});
window.sessionStorage.setItem(`pending.method`, method);
}
從登入介面跳轉回頁面,取出要執行的操作並執行:
if (window.sessionStorage) {
var pendingMethod;
if (pendingMethod = window.sessionStorage.getItem(`pending.method`)) {
window.sessionStorage.removeItem(`pending.method`);
pendingMethod = JSON.parse(pendingMethod);
window[pendingMethod.name].apply($scope, pendingMethod.args || []);
}
}
總結,採用的方式是通過HTTP_REFERER和cookie記錄登入後要跳轉的頁面,通過sessionStorage記錄返回頁面後要執行的javascript方法和引數。