前端實現無感登錄
在現代的前端開發中,用戶體驗是非常重要的一環。無感登錄(也叫自動登錄)就是其中一個提升用戶體驗的關鍵功能。它的目標是讓用戶在登錄后,即使關閉瀏覽器或長時間不操作,也能在下次訪問時自動登錄,而不需要重新輸入賬號和密碼。今天我們就來聊聊如何通過 userToken
和 refreshToken
來實現無感登錄。
什么是 userToken
和 refreshToken
?
在實現無感登錄之前,我們需要先了解兩個重要的概念:userToken
和 refreshToken
。
userToken
(用戶令牌)
它是一個短期有效的憑證,通常在用戶登錄成功后由后端生成并返回給前端。前端會把這個userToken
保存起來(比如存到瀏覽器的localStorage
或cookie
中),并在后續的請求中帶上這個令牌,告訴后端“我是某某用戶”。
但是,userToken
的有效期一般比較短,比如 1 小時,過期后就不能再用了。refreshToken
(刷新令牌)
它是一個長期有效的憑證,通常有效期可以是幾天甚至幾周。refreshToken
的作用是用來“續命”——當userToken
過期時,前端可以用refreshToken
向后端請求一個新的userToken
,從而實現無感登錄。
簡單來說,userToken
是短期的通行證,refreshToken
是長期的備用鑰匙。
無感登錄的工作流程
為了讓用戶在登錄后不需要頻繁輸入賬號密碼,我們可以通過以下流程來實現無感登錄:
1. 用戶登錄
當用戶輸入賬號和密碼登錄時,后端會返回兩個令牌:userToken
和 refreshToken
。前端會把這兩個令牌保存起來,比如:
userToken
存在瀏覽器的localStorage
或cookie
中。refreshToken
存在更安全的地方,比如httpOnly cookie
(這種 cookie 只能被后端訪問,前端無法操作)。
2. 請求時驗證 userToken
用戶登錄后,每次前端向后端發起請求時,都會帶上 userToken
。后端會驗證這個令牌是否有效:
- 如果
userToken
有效,后端會正常處理請求。 - 如果
userToken
過期,前端會用refreshToken
請求一個新的userToken
。
3. 用 refreshToken
刷新 userToken
當 userToken
過期時,前端會自動發送一個請求給后端,帶上 refreshToken
,后端驗證 refreshToken
是否有效:
- 如果
refreshToken
有效,后端會返回一個新的userToken
,前端更新保存的userToken
。 - 如果
refreshToken
也過期了,用戶需要重新登錄。
4. 用戶無感登錄
通過上述流程,用戶只需要在第一次登錄時輸入賬號密碼,之后的登錄過程都是自動完成的,用戶完全感受不到登錄的存在。
實現無感登錄的關鍵點
在實際開發中,我們需要注意以下幾點:
1. 安全性
userToken
和refreshToken
都是敏感信息,不能隨便暴露。尤其是refreshToken
,它的有效期更長,一旦泄露可能會導致嚴重的安全問題。- 建議將
refreshToken
存在httpOnly cookie
中,這樣前端無法直接訪問,能有效防止 XSS 攻擊。
2. 定時刷新
為了避免用戶在操作時突然因為 userToken
過期而中斷,可以在前端設置一個定時器,在 userToken
快過期時提前用 refreshToken
刷新。
3. 處理異常
- 如果
refreshToken
過期了,前端需要引導用戶重新登錄。 - 如果后端返回錯誤(比如令牌被篡改或失效),前端需要清除本地的令牌并跳轉到登錄頁面。
示例代碼
以下是一個簡單的實現流程:
// 假設我們有一個 API 請求函數
async function apiRequest(url, options) {const userToken = localStorage.getItem('userToken');// 在請求頭中帶上 userTokenoptions.headers = {...options.headers,Authorization: `Bearer ${userToken}`,};const response = await fetch(url, options);// 如果 userToken 過期if (response.status === 401) {const refreshToken = getRefreshTokenFromCookie(); // 從 cookie 中獲取 refreshTokenconst newToken = await refreshUserToken(refreshToken); // 用 refreshToken 刷新 userTokenif (newToken) {localStorage.setItem('userToken', newToken); // 更新 userTokenoptions.headers.Authorization = `Bearer ${newToken}`;return fetch(url, options); // 重新發起請求} else {// 如果 refreshToken 也過期了,跳轉到登錄頁面redirectToLogin();}}return response;
}// 刷新 userToken 的函數
async function refreshUserToken(refreshToken) {const response = await fetch('/api/refresh-token', {method: 'POST',headers: {'Content-Type': 'application/json',},body: JSON.stringify({ refreshToken }),});if (response.ok) {const data = await response.json();return data.userToken; // 返回新的 userToken}return null; // 刷新失敗
}
總結
無感登錄的核心是通過 userToken
和 refreshToken
的配合,讓用戶在登錄后可以持續訪問而不需要頻繁輸入賬號密碼。它不僅提升了用戶體驗,還能保證一定的安全性。