Vue Academy · 课时

安全认证模式

令牌存储(内存、localStorage 或 httpOnly Cookie)、静默刷新,以及标签页关闭时退出登录

第 4 / 4 课13 个步骤

安全认证模式 是 CoddyKit 上的免费 Vue Academy 课时。 这是第 4 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Vue Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Vue Academy 课程共包含 4 节课。

token 及其存放位置

单页应用(SPA)使用 token 进行身份验证,但 token 的存放位置决定了您面临的 XSS 和 CSRF 风险。现代做法是将短期访问令牌与长期刷新令牌分开,并以不同方式存储。

localStorage 的问题

将 token 存储在 localStorage 中很方便,但也很危险:任何由 XSS 注入的脚本都可以读取它并将 token 泄露出去。请避免将凭据放在那里。

// AVOID
localStorage.setItem("token", accessToken);

将访问令牌存放在内存中

将访问令牌保存在 JavaScript 变量或响应式 ref 中。重新加载页面后它就会消失,因此即使发生 XSS,攻击者可利用的时间窗口也会小得多,并且磁盘上不会留下任何持久数据。

import { ref } from "vue";

export const accessToken = ref(null);

将刷新令牌存放在 httpOnly Cookie 中

刷新令牌存放在带有 HttpOnly、Secure 和 SameSite 属性的 Cookie 中。JavaScript 无法读取它,因此 XSS 无法窃取它,而且浏览器只会将它发送到您的身份验证端点。

Set-Cookie: refresh=...; HttpOnly; Secure; SameSite=Strict; Path=/auth

附加访问令牌

Axios 请求拦截器会在每次调用中,将内存中的访问令牌添加到 Authorization 标头。

api.interceptors.request.use((config) => {
  if (accessToken.value) {
    config.headers.Authorization = "Bearer " + accessToken.value;
  }
  return config;
});

检测过期:401

访问令牌过期后,服务器会返回 401 Unauthorized。响应拦截器会捕获这个响应并触发刷新操作。

api.interceptors.response.use(
  (res) => res,
  async (error) => {
    if (error.response?.status === 401) {
      // attempt refresh
    }
    return Promise.reject(error);
  }
);

刷新 token

收到 401 后,调用刷新端点。浏览器会自动发送 httpOnly 刷新 Cookie(withCredentials),服务器则返回新的访问令牌。

const { data } = await axios.post("/auth/refresh", null, {
  withCredentials: true
});
accessToken.value = data.accessToken;

重试 original 请求

完成 refreshing 后,使用新令牌重新发送失败的 original 请求,让用户完全察觉不到。

async (error) => {
  const original = error.config;
  if (error.response?.status === 401 && !original._retry) {
    original._retry = true;
    const { data } = await axios.post("/auth/refresh", null, { withCredentials: true });
    accessToken.value = data.accessToken;
    original.headers.Authorization = "Bearer " + data.accessToken;
    return api(original);
  }
  return Promise.reject(error);
}

避免刷新请求风暴

如果许多请求同时返回 401,请将它们排在同一个正在进行的刷新请求之后,避免反复触发刷新端点。

let refreshing = null;
function refresh() {
  if (!refreshing) {
    refreshing = axios.post("/auth/refresh", null, { withCredentials: true })
      .finally(() => { refreshing = null; });
  }
  return refreshing;
}

退出登录

退出登录时,清除内存中的令牌,并调用一个在服务器端清除刷新 Cookie 的端点。

async function logout() {
  accessToken.value = null;
  await axios.post("/auth/logout", null, { withCredentials: true });
}

结合 CSRF 防护

由于刷新 Cookie 会自动发送,请像保护其他通过 Cookie 进行身份验证的路由一样,使用 SameSite 和 CSRF 令牌保护该端点。

快速检查

accessToken 和刷新令牌分别应存储在哪里?

回顾

将 accessToken 存储在内存中的 ref 中(绝不要存入 localStorage),将刷新令牌存储在 HttpOnly Cookie 中。请求拦截器附加持有者令牌;响应拦截器捕获 401,调用刷新端点,更新令牌,并重试 original 请求,同时合并并发刷新请求,配合 CSRF 防护。

免费开始

用 AI 导师学习 HTML — 免费

在浏览器中编写并运行真实代码,获得全天候 AI 导师的即时帮助,并在网页或应用中继续学习。

课程
42
课程
156

常见问题解答

「安全认证模式」课时是免费的吗?

是的 — 「安全认证模式」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Vue Academy 课程的其余内容,请升级到 CoddyKit PRO。 Vue Academy 课程共包含 4 节课。

「安全认证模式」这节课中我会学到什么?

令牌存储(内存、localStorage 或 httpOnly Cookie)、静默刷新,以及标签页关闭时退出登录 你通过在浏览器中直接运行的动手代码来练习 Vue Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 Vue Academy 需要有经验吗?

无需任何先前经验。CoddyKit 上的 Vue Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 4 节课,共 4 节。

「安全认证模式」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 Vue Academy 课中编写并运行代码吗?

能。每节 Vue Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. Vue 中的 XSS 防护
  2. 使用 Vue 配置内容安全策略(CSP)
  3. Vue SPA 中的 CSRF 防护
  4. 安全认证模式
← 返回 Vue Academy