在前端开发中,用户的身份验证和会话管理是一个重要的部分。通常情况下,我们使用 JWT(JSON Web Token)来实现用户的身份验证,JWT 在用户登录后会生成一个 token,并将其存储在客户端(如 LocalStorage 或 Cookie)中。然而,token 有一定的有效期,这就需要在 token 过期后进行刷新,以防用户再次登录。

无感刷新是指在用户未察觉的情况下,自动刷新 token,确保用户能够无缝地继续使用应用而不会受到身份验证的影响。在这篇文章中,我们将探讨如何在前端实现无感刷新,包括代码示例和最佳实践。

1. 实现思路

通常,token 刷新的流程如下:

  • 用户登录后,后端生成 access token 和 refresh token。
  • access token 有短期有效性(例如 15 分钟),而 refresh token 则具有较长的有效性(例如 7 天)。
  • 在前端每次请求时,检查 access token 是否即将过期(例如,5 分钟前)。
  • 如果即将过期,使用 refresh token 请求新的 access token。
  • 更新本地存储中的 access token,并继续后续请求。

2. 代码示例

下面是一个简单的 Vue.js 应用示例,演示如何在应用中实现无感刷新功能。

安装依赖

首先,确保您已安装 Axios(用于发送 HTTP 请求):

npm install axios

创建 Token 管理模块

我们可以创建一个 tokenService.js 模块来管理 token 的获取和刷新。

// tokenService.js
import axios from 'axios';

let accessToken = null;
let refreshToken = null;

// 设置 token
export const setTokens = (newAccessToken, newRefreshToken) => {
    accessToken = newAccessToken;
    refreshToken = newRefreshToken;

    // 将 token 存储到 localStorage
    localStorage.setItem('access_token', accessToken);
    localStorage.setItem('refresh_token', refreshToken);
};

// 获取 access token
export const getAccessToken = () => {
    if (!accessToken) {
        accessToken = localStorage.getItem('access_token');
    }
    return accessToken;
};

// 刷新 access token
export const refreshAccessToken = async () => {
    const response = await axios.post('/api/refresh', {
        refresh_token: refreshToken,
    });
    if (response.data && response.data.access_token) {
        setTokens(response.data.access_token, response.data.refresh_token);
    }
};

// 添加请求拦截器
axios.interceptors.request.use(async (config) => {
    const token = getAccessToken();
    const expiryTime = decodeJwt(token).exp * 1000;
    const currentTime = Date.now();

    // 检查 token 是否即将过期
    if (expiryTime - currentTime < 5 * 60 * 1000) {
        // 如果即将过期,刷新 token
        await refreshAccessToken();
    }

    config.headers.Authorization = `Bearer ${getAccessToken()}`;
    return config;
}, error => {
    return Promise.reject(error);
});

// 解码 JWT
const decodeJwt = (token) => {
    if (!token) return {};
    const payload = token.split('.')[1];
    return JSON.parse(atob(payload));
};

3. 使用 Token 管理模块

在应用中,只需在用户登录时调用 setTokens 方法设置 token,之后所有的请求都会自动使用拦截器进行 token 的管理。

// 在用户登录时
import { setTokens } from './tokenService';

const loginUser = async (username, password) => {
    const response = await axios.post('/api/login', { username, password });
    if (response.data) {
        setTokens(response.data.access_token, response.data.refresh_token);
    }
};

// 在组件中发起请求
const fetchData = async () => {
    const response = await axios.get('/api/data');
    console.log(response.data);
};

4. 结论

无感刷新机制可以极大地提高用户体验,用户不会因为 token 过期而被迫重新登录。本文中介绍的代码示例展示了如何在前端利用 Axios 拦截器和 token 管理模块实现这一功能。在实际开发中,需注意将 token 存储在安全的位置,并遵循最佳安全实践,以防止 XSS 攻击等安全隐患。

点赞(0) 打赏

微信小程序

微信扫一扫体验

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部