Token存储选择:LocalStorage、Cookie还是内存?几种方案对比

更新日期: 2025-10-12阅读: 99标签: token

很多开发者刚开始做项目时都会遇到这个问题:用户登录后拿到的token,到底应该存在哪里?LocalStorage、SessionStorage、Cookie,还是直接放在内存中?为什么不同的网站做法不一样?

这个问题确实让人困惑。每次看到不同项目使用不同的存储方式,很多人都会想:到底哪种方法才是正确的?


为什么token存储这么重要?

想象一下,你家的钥匙你会放在哪里?随身带着?藏在门垫下面?还是交给保安保管?如果放错了地方,小偷就可能进你家门。

token就是用户进入系统的钥匙。如果存错了地方,黑客就能冒充用户登录账号,后果很严重。


不同存储方式的特点

1. LocalStorage(本地存储)

  • 永久保存,除非手动删除

  • 同一个网站的任何页面都能读取

  • 刷新页面或关闭浏览器都不会丢失

  • 如果网站有安全漏洞,token可能被偷

  • 需要手动添加到请求头中

2. SessionStorage(会话存储)

  • 只在当前浏览器标签页有效

  • 同一个网站可以读取

  • 适合临时操作

  • 关闭浏览器标签页就消失

  • 同样有安全风险

  • 需要手动管理

3. Cookie

  • 可以设置过期时间

  • 可以设置HttpOnly(JavaScript读不到)

  • 可以设置Secure(只通过HTTPS传输)

  • 可以设置SameSite(防止某些攻击)

  • 自动随着请求发送

  • 容量有限制(约4KB)

  • 每次请求都会携带,可能浪费流量

4. 内存存储

  • 页面刷新就丢失

  • 完全由前端控制,不持久保存

  • 最快最安全,但生命周期最短

  • 不适合需要持久保存的情况

  • 关闭标签页就没了


为什么很多人喜欢用LocalStorage?

很多前端开发者的第一反应是:"用LocalStorage最方便!"

确实,几行代码就能搞定:

// 保存token
localStorage.setItem('token', res.token);

// 发送请求时使用
axios.defaults.headers.common['Authorization'] = localStorage.getItem('token');

方便是真的方便,但安全问题也需要考虑。

安全例子: 如果网站有个评论区,用户输入的内容没有做安全检查,黑客可能插入这样的代码:

<script>
  fetch('/steal?token=' + localStorage.getItem('token'))
</script>

用户打开页面时,这段代码执行,你的token就被发送到黑客的服务器了。

如果token存在HttpOnly Cookie里,JavaScript读不到,这种攻击就失效了。


用Cookie就绝对安全吗?

也不是。Cookie也有自己的问题。比如黑客可能诱导你访问一个恶意页面:

<img src="https://yourbank.com/transfer?to=hacker&amount=100000" />

如果你的登录信息在Cookie里,浏览器会自动带上Cookie,请求就可能成功。用户什么都没做,钱可能就被转走了。


四种实用的解决方案

方案一:前后端分离 + JWT + LocalStorage(最常用)

这是目前大多数新项目采用的方式。

技术组合:

  • 前端:vuereact框架

  • 后端:SpringBoot、Express等,提供api接口

  • 通信:Axios + JWT

  • Token存储:localStorage

部署方式:
用户浏览器访问前端网站,前端通过API与后端通信。

登录流程:

  1. 用户登录

  2. 后端验证用户名密码,生成JWT

  3. 返回给前端:{ token: "xxxxxx" }

  4. 前端存入localStorage

  5. 后续请求时,前端手动添加请求头:

axios.defaults.headers.common['Authorization'] = 'Bearer ' + token
  1. 后端解析JWT,验证身份

优点:

  • 前后端完全分开,各自独立开发部署

  • 适合现代架构

  • 开发简单,调试方便

缺点:

  • 有安全风险

  • 需要手动管理token

  • 跨域配置稍麻烦

适合场景:

  • 后台管理系统

  • 普通网站、商城

  • 需要快速上线的项目

这是目前最主流的方案,大部分新项目都这样用。

方案二:前后端合并部署(传统做法)

把前端代码打包后放到后端的静态资源目录里,由后端统一提供页面和API。

访问方式:

  • 页面:http://localhost:8080/

  • API:http://localhost:8080/api/xxx

优点:

  • 部署简单

  • 没有跨域问题

  • 适合小型项目

缺点:

  • 前后端耦合,不利于独立更新

  • 静态资源由后端服务提供,性能可能不如专用服务器

  • 不适合高并发场景

适合场景:

  • 内部工具

  • 学习项目

  • 对性能要求不高的系统

这种方案在企业级项目中逐渐减少,但在小项目中仍然常见。

方案三:双Token机制(高安全要求)

这是银行、金融等高安全性系统中常用的专业做法。

方案核心:

  • access_token:短期JWT,存在前端内存,用于API认证

  • refresh_token:长期token,存在HttpOnly Cookie,用于刷新access_token

流程:

  1. 登录成功

    • 后端:设置HttpOnly Cookie存储refresh_token

    • 响应体:返回access_token

  2. 前端:

    • 存access_token到内存

    • 请求时添加Authorization头

  3. access_token过期后:

    • 调用刷新接口

    • 浏览器自动携带refresh_token

    • 获取新的access_token

优点:

  • 安全性高

  • 即使access_token泄露,有效期也很短

  • 极高的安全性

缺点:

  • 实现复杂

  • 需要后端配合

  • 要处理好刷新机制

适合场景:

  • 银行、支付系统

  • 高权限后台

  • 对安全要求极高的系统

方案四:使用Cookie + Session(传统安全做法)

使用Spring Security + Session,登录后设置HttpOnly的Session Cookie。

前端不需要处理token,浏览器会自动携带Cookie。

优点:

  • 安全性高

  • 后端可以管理session

  • 适合内部系统

缺点:

  • 需要处理跨站请求伪造问题

  • 不适合现代架构

  • 跨域配置复杂

适合场景:

  • 传统企业系统

  • 内部管理系统

  • 已有相关架构的项目


四种方案对比

方案安全性易用性推荐度适用场景
前后端分离 + JWT + LocalStorage⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐90%的新项目
前后端合并部署⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐小项目、学习
双Token机制⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐高安全系统
Cookie + Session⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐传统企业系统

实用建议

  1. 如果你是新手或做小项目:用前后端分离 + JWT + localStorage,简单直接

  2. 如果你做后台系统或普通网站:同上,但要做好安全防护(输入检查、安全策略等)

  3. 如果你做金融或高权限系统:用双Token机制,安全第一

  4. 如果你是传统企业或内部系统:可以考虑Cookie + Session,但要配置好安全设置

目前Vue + SpringBoot的标准做法是:前后端分离 + JWT + LocalStorage。

虽然这种方案有安全风险,但因为开发效率高、架构清晰、适合现代部署等优势,已经成为主流。

安全问题不是单靠"不用localStorage"就能解决的,而是需要:

  • 严格的输入验证

  • 安全策略配置

  • 定期安全检查

  • 使用安全头部

技术选择,永远是在安全、效率、成本之间找到平衡。


实际代码示例

使用LocalStorage的基本例子

// 登录后保存token
function loginSuccess(token) {
  localStorage.setItem('auth_token', token);
}

// 发送请求时添加token
function apiRequest(url, data) {
  const token = localStorage.getItem('auth_token');
  return fetch(url, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'Authorization': `Bearer ${token}`
    },
    body: JSON.stringify(data)
  });
}

// 退出登录时清除
function logout() {
  localStorage.removeItem('auth_token');
}

双Token机制示例

let accessToken = '';

// 登录处理
async function login(credentials) {
  const response = await fetch('/api/login', {
    method: 'POST',
    headers: {'Content-Type': 'application/json'},
    body: JSON.stringify(credentials)
  });
  
  const data = await response.json();
  accessToken = data.access_token;
  // refresh_token会自动保存在HttpOnly Cookie中
}

// 自动刷新token
async function refreshToken() {
  try {
    const response = await fetch('/api/refresh', {
      method: 'POST',
      credentials: 'include' // 自动携带Cookie
    });
    const data = await response.json();
    accessToken = data.access_token;
    return true;
  } catch (error) {
    return false;
  }
}

选择哪种方案,要根据你的具体需求和项目特点来决定。对于大多数项目来说,方案一就足够了,但要知道它的优缺点,并做好相应的安全措施。

本文内容仅供个人学习/研究/参考使用,不构成任何决策建议或专业指导。分享/转载时请标明原文来源,同时请勿将内容用于商业售卖、虚假宣传等非学习用途哦~感谢您的理解与支持!

链接: https://fly63.com/article/detial/13001

深入理解令牌认证机制(token)

以前的开发模式是以MVC为主,但是随着互联网行业快速的发展逐渐的演变成了前后端分离,若项目中需要做登录的话,那么token成为前后端唯一的一个凭证。token即标志、记号的意思,在IT领域也叫作令牌。

koa+jwt实现token验证与刷新

JSON Web Token (JWT)是一个开放标准(RFC 7519),它定义了一种紧凑的、自包含的方式,用于作为JSON对象在各方之间安全地传输信息。该信息可以被验证和信任,因为它是数字签名的。

深度理解token

Token 是在服务端产生的。如果前端使用用户名/密码向服务端请求认证,服务端认证成功,那么在服务端会返回 Token 给前端。前端可以在每次请求的时候带上 Token 证明自己的合法地位。如果这个 Token 在服务端持久化(比如存入数据库

axios如何利用promise无痛刷新token

最近遇到个需求:前端登录后,后端返回token和token有效时间,当token过期时要求用旧token去获取新的token,前端需要做到无痛刷新token,即请求刷新token时要做到用户无感知。

axios如何利用promise无痛刷新token?

前端登录后,后端返回token和token有效时间段tokenExprieIn,当token过期时间到了,前端需要主动用旧token去获取一个新的token,做到用户无感知地去刷新token。

前后端分离:使用 token 登录解决方案

这篇文章写一下前后端分离下的登录解决方案,目前大多数都采用请求头携带 Token 的形式。首次登录时,后端服务器判断用户账号密码正确之后,根据用户id、用户名、定义好的秘钥、过期时间生成 token

vue+axios设置token,增加请求拦截器

第一次登录的时候,前端调后端的登陆接口,发送用户名和密码,后端收到请求,验证用户名和密码,验证成功,就给前端返回一个token,前端拿到token,将token存储到localStorage和vuex中

Vue 消除Token过期时刷新页面的重复提示

页面长时间未操作,再刷新页面时,第一次弹出“token失效,请重新登录!”提示,然后跳转到登录页面,接下来又弹出了n个“Token已过期”的后端返回消息提示。当前页面初始化,有多个向后端查询系统参数的调用,代码如下:

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!