返回

无感刷新不费力,双token完美实现,后端亲传代码Get!

前端

无感刷新:双令牌机制的终极指南

什么是无感刷新?

无感刷新是一种前端技术,旨在为用户提供无缝的页面体验。它允许用户在页面上进行操作,无需等待页面重新加载或刷新。这创造了一种类似于单页应用程序的体验,但使用的是传统的多页应用程序模型。

双令牌机制

无感刷新的关键在于双令牌机制。它使用两个不同的令牌:

  • 访问令牌 (accessToken) :用于对每个请求进行身份验证。
  • 刷新令牌 (refreshToken) :用于请求新的访问令牌。

实现流程

  1. 用户登录并接收访问令牌和刷新令牌。
  2. 访问令牌存储在 cookie 中,用于验证后续请求。
  3. 刷新令牌存储在 localStorage 中,用于在访问令牌过期后获取新的访问令牌。
  4. 当访问令牌过期时,前端向后端请求新的访问令牌,并使用刷新令牌进行身份验证。
  5. 后端验证刷新令牌并颁发新的访问令牌。

前端代码(Vue3 + Vite + axios)

安装 axios

npm install axios

创建 axios 实例

import axios from "axios";

const instance = axios.create({
  baseURL: "http://localhost:3000",
  timeout: 10000,
});

在请求拦截器中添加访问令牌

instance.interceptors.request.use((config) => {
  const accessToken = localStorage.getItem("accessToken");
  if (accessToken) {
    config.headers.Authorization = `Bearer ${accessToken}`;
  }
  return config;
});

在响应拦截器中处理访问令牌过期

instance.interceptors.response.use(
  (response) => {
    return response;
  },
  (error) => {
    if (error.response && error.response.status === 401) {
      // 访问令牌过期,使用刷新令牌请求新的访问令牌
      const refreshToken = localStorage.getItem("refreshToken");
      if (refreshToken) {
        return instance
          .post("/refresh", { refreshToken })
          .then((res) => {
            // 更新访问令牌和刷新令牌
            localStorage.setItem("accessToken", res.data.accessToken);
            localStorage.setItem("refreshToken", res.data.refreshToken);
            // 重新发送请求
            return instance(error.config);
          })
          .catch((err) => {
            // 刷新令牌也过期了,需要重新登录
            window.location.href = "/login";
          });
      } else {
        // 刷新令牌也过期了,需要重新登录
        window.location.href = "/login";
      }
    }
    return Promise.reject(error);
  }
);

后端代码(koa2)

创建 koa2 实例

const Koa = require("koa");
const app = new Koa();

定义登录接口

app.post("/login", async (ctx) => {
  const { username, password } = ctx.request.body;
  if (username === "admin" && password === "123456") {
    const accessToken = jwt.sign({ username }, "secret", { expiresIn: "1h" });
    const refreshToken = jwt.sign({ username }, "secret", { expiresIn: "7d" });
    ctx.body = { accessToken, refreshToken };
  } else {
    ctx.status = 401;
    ctx.body = "Unauthorized";
  }
});

定义刷新访问令牌接口

app.post("/refresh", async (ctx) => {
  const { refreshToken } = ctx.request.body;
  if (refreshToken) {
    const decoded = jwt.verify(refreshToken, "secret");
    const accessToken = jwt.sign({ username: decoded.username }, "secret", { expiresIn: "1h" });
    ctx.body = { accessToken };
  } else {
    ctx.status = 401;
    ctx.body = "Unauthorized";
  }
});

启动 koa2 实例

app.listen(3000);

注意事项

  • 访问令牌的有效期应该足够短以确保安全性。
  • 刷新令牌的有效期应该足够长以减少向后端请求的次数。
  • 将访问令牌和刷新令牌存储在安全的地方以防止被窃取。
  • 在前端中使用 axios 库时,务必在请求拦截器中添加访问令牌。
  • 在后端中使用 koa2 框架时,务必定义登录和刷新访问令牌的接口。

结论

无感刷新是一种改变用户体验的技术,通过消除页面刷新来提供更加流畅的体验。双令牌机制是实现无感刷新的关键,它允许应用程序在访问令牌过期时在后台无缝地获取新的访问令牌。通过遵循本文中概述的步骤和考虑注意事项,你可以成功地将无感刷新整合到你的应用程序中。

常见问题解答

1. 为什么需要使用双令牌机制?

双令牌机制可以防止单点故障,如果一个令牌被盗用或过期,另一个令牌仍然可用。

2. 访问令牌和刷新令牌的有效期应该有多长?

访问令牌的有效期通常设置为几分钟到几小时,而刷新令牌的有效期可以长达几天或几周。

3. 应该在哪里存储访问令牌和刷新令牌?

访问令牌应该存储在 cookie 中,而刷新令牌应该存储在 localStorage 中。

4. 如何防止访问令牌被盗用?

可以采取多种措施来防止访问令牌被盗用,例如使用安全传输层(SSL/TLS)加密传输,并在服务器端存储令牌而不是客户端。

5. 如何处理刷新令牌也过期的情况?

如果刷新令牌也过期,用户需要重新登录应用程序。