前端实现无感登录
在现代的前端开发中,用户体验是非常重要的一环。无感登录(也叫自动登录)就是其中一个提升用户体验的关键功能。它的目标是让用户在登录后,即使关闭浏览器或长时间不操作,也能在下次访问时自动登录,而不需要重新输入账号和密码。今天我们就来聊聊如何通过 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
的配合,让用户在登录后可以持续访问而不需要频繁输入账号密码。它不仅提升了用户体验,还能保证一定的安全性。