登录突然失效:Axios 拦截器判空、localStorage 脏数据与环境变量踩坑

登录突然失效:Axios 拦截器判空、localStorage 脏数据与环境变量踩坑

现象:最开始能登录,后来加了"普通用户登录/角色选择"之后,点击登录按钮没反应;控制台报错:

  • TypeError: Cannot read properties of undefined (reading 'status')(request.js)
  • TypeError: Cannot read properties of null (reading 'token')(request.js)

结论:登录业务本身没坏,坏的是异常分支的健壮性 :网络失败时 Axios 没有 response、localStorage 存了脏值导致 token 读取崩溃,最终让页面看起来"按钮失灵"。


1. 背景与系统结构

  • 前端:Vue3 + Vite + Element Plus + Axios
  • 后端:SpringBoot(端口 9090

前端通过 baseURL = import.meta.env.VITE_BASE_URL 请求后端接口(例如 /login)。


2. 现象与报错意味着什么

2.1 报错 1:

Cannot read properties of undefined (reading 'status')

典型代码形态(伪代码):

js 复制代码
// 响应拦截器 error 分支
if (error.response.status === 404) {
  ...
}

为什么会出现 error.response === undefined

Axios 的错误分两大类:

  1. HTTP 错误(有响应) :比如 404、500,此时 error.response 存在。
  2. 网络层错误(无响应)
  • 后端没启动/端口不对
  • 后端重启中/短暂不可用
  • 请求超时
  • 跨域被浏览器拦截
  • 连接被拒绝(ERR_CONNECTION_REFUSED)

这类情况下,浏览器根本拿不到 HTTP 响应,所以 Axios 也就没有 error.response

因此直接读 error.response.status 就会抛异常,把你的 Promise 链直接打断

页面表现:点击登录无反应(其实是 JS 报错中断了后续逻辑)。

2.2 报错 2:

Cannot read properties of null (reading 'token')

典型代码:

js 复制代码
let user = JSON.parse(localStorage.getItem('xm-user') || '{}')
config.headers['token'] = user.token || ''

为什么 JSON.parse 之后会是 null?

当 localStorage 中保存的是字符串:

text 复制代码
"null"

那么:

js 复制代码
JSON.parse('null') // => null

于是 user 变成 null,再读 user.token 就报错。

这种"突然坏掉"最常见的原因是:某次流程(例如退出/切换角色)把 xm-user 写成了 null 或非法 JSON,之后每次请求都会在拦截器崩掉。


3. 为什么"没改关键代码,但突然不能登录"?

关键点:成功路径一直没问题,问题出在"异常路径"。

以前能登录,是因为:

  • 后端一直稳定可用 → 没触发网络错误分支
  • localStorage 没出现脏值 → 没触发 token 读取崩溃

后来突然不行,往往只需要发生一次:

  • 后端短暂不可用(哪怕 1 次)
  • 或者某次逻辑把 xm-user 写成了 "null"

就会触发拦截器报错,从用户视角看就是"按钮突然不灵"。

加了"普通用户登录/角色选择"后,更容易触发边界情况:

  • 初次进入未登录、token 为空
  • 切换角色导致缓存被覆盖
  • 退出逻辑写错,把对象置空

这些都不是"登录关键业务逻辑",但会让系统更频繁进入异常分支,从而暴露隐患。


4. 排查思路(推荐按这个顺序)

4.1 先看 Network:请求到底有没有成功发出去?

  • 如果请求状态是 200/401/500 → 属于 HTTP 有响应
  • 如果请求是 (failed)ERR_CONNECTION_REFUSEDCORS → 属于 网络层无响应

网络层无响应时,error.response 一定可能是 undefined

4.2 再看 localStorage:xm-user 是不是脏了?

打开 DevTools → Application → Local Storage:

  • xm-user 如果是 "null" 或非法 JSON → 一定会触发 token 报错。

快速修复:删掉 xm-user 再刷新页面。

4.3 最后核对环境变量:是否跑到 production 配置?

  • npm run dev 使用 .env.development
  • npm run build / preview 使用 .env.production

如果 .env.production 写错(例如 http://:9090 缺 host),构建产物一定连不上后端。


5. 最小改动修复(不改变原业务)

本次修复目标:只增强容错,不改原有登录成功/失败逻辑与接口协议

5.1 request.js:对 error.response 判空

核心思想:网络错误时没有 response,不要读 status

js 复制代码
if (!error || !error.response) {
  ElMessage.error('网络异常:无法连接服务器')
  return Promise.reject(error)
}

这样就不会再出现 reading 'status' 的 JS 崩溃。

5.2 request.js:对 localStorage 的 xm-user 做健壮解析

核心思想:localStorage 可能是 "null"、空字符串、非法 JSON、或解析后不是对象。

js 复制代码
const userStr = localStorage.getItem('xm-user')
let user = {}
try {
  user = userStr ? JSON.parse(userStr) : {}
} catch (e) {
  user = {}
}
if (!user || typeof user !== 'object') user = {}
config.headers['token'] = user.token || ''

这样即使缓存坏了,也不会因为读 token 崩溃。

5.3 Login.vue:为登录请求补 .catch 提示

核心思想:失败时要给用户反馈,否则看起来像"按钮没反应"。

js 复制代码
request.post('/login', data.form)
  .then(...)
  .catch(err => {
    ElMessage.error(err?.message || '登录失败')
  })

5.4 修正 .env.production 的 baseURL

如果你以后跑构建产物(build/preview/部署),要确保:

dotenv 复制代码
VITE_BASE_URL='http://localhost:9090'

避免出现 http://:9090 这种无效地址。


6. 结果

  • npm run dev 下登录恢复正常
  • 网络异常/后端不可达时不再崩溃,而是明确提示"无法连接服务器"
  • localStorage 脏数据不再导致拦截器读 token 崩溃

7. 预防建议(同类项目通用)

  • Axios 拦截器里永远不要假设 error.response 存在
  • localStorage 读取要做容错:解析失败、null、类型不对都要兜底
  • 登录请求必须有 .catch(哪怕只提示一句)
  • 开发/生产环境变量要区分清楚,避免 build 产物用错 baseURL

附:一句话总结

这次"突然不能登录"不是后端登录接口坏了,而是前端在网络错误/缓存异常时直接抛 JS 异常导致逻辑中断;通过对 error.responsexm-user 做判空容错,并补充 .catch 提示,就能在不改业务的前提下恢复稳定登录。

相关推荐
傻乐u兔10 小时前
C语言进阶————指针4
c语言·开发语言
大模型玩家七七10 小时前
基于语义切分 vs 基于结构切分的实际差异
java·开发语言·数据库·安全·batch
历程里程碑10 小时前
Linux22 文件系统
linux·运维·c语言·开发语言·数据结构·c++·算法
恋猫de小郭10 小时前
Flutter Zero 是什么?它的出现有什么意义?为什么你需要了解下?
android·前端·flutter
牛奔11 小时前
Go 如何避免频繁抢占?
开发语言·后端·golang
寻星探路15 小时前
【深度长文】万字攻克网络原理:从 HTTP 报文解构到 HTTPS 终极加密逻辑
java·开发语言·网络·python·http·ai·https
崔庆才丨静觅16 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
lly20240616 小时前
Bootstrap 警告框
开发语言
2601_9491465317 小时前
C语言语音通知接口接入教程:如何使用C语言直接调用语音预警API
c语言·开发语言
曹牧17 小时前
Spring Boot:如何测试Java Controller中的POST请求?
java·开发语言