前端Token管理终极指南:安全存储 + 无感刷新

一、引言:为什么Token管理是前端核心能力

  • 现代 Web 应用的认证架构演进 :Session -> JWT -> OAuth2.0
  • 前端 Token 管理的三大挑战: 安全性、无感刷新、状态同步

二、双 Token 机制 :安全架构

1、令牌分工原理

json 复制代码
// 令牌结构示例
{
  "access_token": "eyJhbG...",  // 短期令牌(30分钟)
  "refresh_token": "f7a2e...", // 长期令牌(7天)
  "expires_in": 1800          // 过期时间
}
  • access_token:高频使用,携带用户身份,必须短时效
  • refresh_token:仅用于刷新,绝不出现在常规请求中

2.安全存储方案对比

存储位置 适用令牌类型 安全等级 生命周期 风险
sessionStorage access_token ★★★★☆ 标签页关闭时失效 XSS 可读取
内存变量 refresh_token ★★★★★ 页面刷新即丢失 无法持久化
HttpOnly Cookie refresh_token ★★★★★ 可设长时效 需防 CSRF
localStorage 不推荐 ★☆☆☆☆ 永久存储 XSS 完全暴露

💡 黄金法则:Access Token 存易失位置,Refresh Token 用 HttpOnly Cookie

3、无感刷新实战:Axios 拦截器深度优化

javascript 复制代码
// 请求拦截器
service.interceptors.request.use(
  (config) => {
    try {
      // 从sessionStorage获取access_token
      const token = sessionStorage.getItem('access_token')
      if (token) {
        config.headers.Authorization = `${token}`
      }
      return config
    } catch (error) {
      console.error('获取token失败:', error)
      return config
    }
  },
  (error) => {
    return Promise.reject(error)
  },
)
javascript 复制代码
// 响应拦截器
service.interceptors.response.use(
  (response) => {
    return response
  },
  async (error) => {
    // 获取错误响应状态
    const { response } = error

    if (response?.status === 401) {
      // token过期
      const config = error.config
      if (!isRefreshing) {
        isRefreshing = true
        try {
          // 尝试刷新token
          const userStore = useUserStore()
          const refreshResult = await userStore.refreshToken()
          if (refreshResult) {
            // 重新设置token
            const newToken = sessionStorage.getItem('access_token')
            config.headers.Authorization = newToken
            // 重新请求队列中的请求
            requests.forEach((cb) => cb(newToken))
            requests = []
            // 重试当前请求
            return service(config)
          }
        } catch (err) {
          console.error('刷新token失败:', err)
          // 刷新失败,清空token并跳转到登录页
          const userStore = useUserStore()
          userStore.clearUserInfo()
          window.location.href = '/login'
          return Promise.reject(err)
        } finally {
          isRefreshing = false
        }
      } else {
        // 正在刷新token,将请求加入队列
        return new Promise((resolve) => {
          requests.push((token) => {
            config.headers.Authorization = `${token}`
            resolve(service(config))
          })
        })
      }
    }
    return Promise.reject(error)
  },

三、用户信息pinia持久化

做用户功能时,刷新一下页面用户信息就没了,我是用pinia持久化的,然后发现是没有下载插件和配置pinia-plugin-persistedstate。

javascript 复制代码
{
    persist: {
      // 存储在 sessionStorage 中的键名
      key: 'user-store',
      
      // 使用 sessionStorage 作为存储方式
      storage: window.sessionStorage,
      
      // 只持久化 store 中的 userInfo 数据
      paths: ['userInfo']
    }
}

这个配置的作用是:

1.持久化存储:

  • 当页面刷新时,Pinia store 中的数据会被重置
  • 通过这个配置,指定的数据会自动保存到 sessionStorage 中
  • 页面刷新后,数据会自动从 sessionStorage 恢复到 store 中

2.选择性持久化:

  • paths: ['userInfo'] 表示只持久化 store 中的 userInfo 数据
  • 其他数据如 tokenInfo 不会被持久化
  • 这样可以更精确地控制哪些数据需要保存

3.使用 sessionStorage:

  • 数据存储在 sessionStorage 中,而不是 localStorage
  • 这意味着数据只在当前会话期间有效
  • 关闭浏览器后数据会被清除,保证了安全性

举个例子:

arduino 复制代码
// 用户登录后,userInfo 会被自动保存到 sessionStorage
userInfo.value = {
  username: 'test',
  email: 'test@example.com'
}

// 页面刷新后,userInfo 会自动从 sessionStorage 恢复
// 不需要手动处理恢复逻辑

主要好处:

  1. 避免页面刷新后用户信息丢失
  2. 不需要手动管理数据的存储和恢复
  3. 通过 sessionStorage 确保了数据的安全性

四、架构图解:

相关推荐
三坛海会大神55521 小时前
k8s(九)安全机制
安全·容器·kubernetes
啊啊啊啊8431 天前
k8s lngress与安全机制
安全·容器·kubernetes
qyhua1 天前
【Linux运维实战】彻底修复 CVE-2011-5094 漏洞
linux·运维·安全
Andya_net1 天前
网络安全 | 深入了解 X.509 证书及其应用
服务器·安全·web安全
骥龙2 天前
2.8、权限的终极目标:提权与持久化
安全·网络安全
SuperherRo2 天前
JS逆向-安全辅助项目&Yakit热加载&魔术方法&模版插件语法&JSRpc进阶调用&接口联动
javascript·安全·yakit·jsrpc·热加载
梵得儿SHI2 天前
Java 反射机制深度剖析:性能与安全性的那些坑
java·开发语言·安全·反射·动态代理·性能·反射机制
来旺2 天前
互联网大厂Java面试全解析及三轮问答专项
java·数据库·spring boot·安全·缓存·微服务·面试
Brianna Home2 天前
博客安全攻防演练:从攻击者视角构筑铜墙铁壁
网络·数据库·安全·oracle
施嘉伟2 天前
SQL Server安全配置全面检查与优化方案
数据库·安全