一次登录问题排查:接口没错,错的是旧业务逻辑

前几天,我碰到一个登录问题。现象不复杂:SSO 登录成功了,但是系统内部页面不正常。继续往下看,系统菜单接口还提示"令牌不合法"。

一开始我以为这是接口问题。后来发现,不是。它更像是一个业务问题,只不过最后表现成了接口报错。

一、现象是什么

系统里原来有一套登录逻辑,大意如下:

scss 复制代码
function ssoLoginFlow(ticket) {
  const result = requestSSO(ticket)

  if (result.success) {
    if (result.needChangePassword === false) {
      saveFormalToken(result.token)
      loadUserInfo()
    } else {
      saveTemporaryToken(result.token)
    }
  }
}

这段伪代码的意思很清楚:

  • 如果不是首次登录,就写正式 token
  • 如果是首次登录,就走另一套"改密码"逻辑

看起来完全正常。 问题在于,系统现在已经不是按这个业务规则在跑了。

二、我最开始为什么会想错

因为我被最显眼的错误带偏了。

排查时先看到一个旧接口 404。 看到 404,我的第一反应通常是,是不是:

  • 地址错了?
  • 域名没切干净?
  • 接口废弃了?

这些想法都很自然,但它们有一个共同问题:

都在盯着报错的接口,没有盯着系统状态。

后来我才意识到,真正该问的不是:

哪个请求失败了?

而是:

登录成功以后,系统有没有真正进入"已登录可用"的状态?

这是两个问题。

三、什么叫"状态机"

很多人听到"状态机"这个词,会觉得很抽象。其实很简单,你可以把它理解成一句话:

一个系统会处在不同状态里,每发生一个动作,它就从当前状态切到下一个状态。

这就叫状态机。

比如自动售货机:

  • 待机
  • 已投币
  • 已选商品
  • 出货中

你投币,它从"待机"切到"已投币"。

你选商品,它从"已投币"切到"已选商品"。

登录系统也是一样。

四、登录为什么本质上是一个状态机

很多人以为登录就是调一个接口,其实不是。

登录更像下面这串过程:

  1. 用户未登录
  2. SSO 认证成功
  3. 前端拿到 token
  4. 前端把 token 存起来
  5. 路由守卫判断"这是已登录用户"
  6. 系统拉取菜单和权限
  7. 动态生成路由
  8. 页面正常进入后台

画成示意图就是这样:

css 复制代码
flowchart TD
    A[未登录] --> B[SSO 认证成功]
    B --> C[拿到 token]
    C --> D[写入正式登录态]
    D --> E[路由守卫放行]
    E --> F[拉取菜单权限]
    F --> G[生成路由]
    G --> H[进入后台页面]

这张图最重要的一点是:

登录成功,只代表走到了前面几步,不代表后面都已经正常。

只要中间某一步没走对,页面表现就会很怪:

  • 登录成功但进不去
  • 能进去但菜单是空的
  • 菜单有了但接口报权限错

这类问题,看起来像接口问题,实际上常常是状态没切对。

五、这次问题真正卡在哪里

后来我才知道,业务规则早就变了。 以前的业务是:

  • 用户可能是首次登录
  • 首次登录要强制改密码
  • 所以要根据一个标记位,决定 token 该怎么处理

现在的业务变成了:

  • 用户直接注册
  • 使用工号密码登录
  • 不再有"首次登录强制改密码"这套流程

也就是说,代码还在执行一套旧规则,但业务已经换了。找到了原因,后来真正起作用的改法,其实很简单:

scss 复制代码
function ssoLoginFlow(ticket) {
  const result = requestSSO(ticket)

  if (result.success) {
    saveFormalToken(result.token)
  }
}

意思就是:

  • SSO 成功
  • 直接建立正式登录态

一改完,后面的菜单、路由、权限链路就顺了。

所以这次修好的,不是某个接口地址,也不是某个请求头。真正修好的是:

代码终于和现在的业务规则对齐了。

六、为什么菜单接口会报"令牌不合法"

这个现象最容易让人迷糊。

明明登录成功了,为什么菜单接口还不认? 因为后面的菜单接口、权限接口、路由守卫,依赖的是"正式登录态"。

如果登录成功了,但系统没有把你放进"正式已登录用户"这个状态里,那后面的模块就会认为:

这个人虽然看起来像登录了,但状态还不完整。

这就像你进了小区大门,但没有电梯卡。

门禁放你进来了,不代表电梯也认你。

很多登录问题,就是这种感觉:

好像已经登录了,但又没完全登录。

七、这次真正暴露出来的盲区

回头看,这次不是代码能力的问题,更像是思维习惯的问题。

1. 默认"旧代码还在,就说明旧逻辑还有效"

这是很常见的误区。真实项目里经常是:

  • 需求已经变了
  • 代码没清理
  • 老分支还在跑

所以以后看到老逻辑,不能只问:

它现在在干什么?

还要问:

它现在还该不该存在?

2. 过度关注接口报错,忽略状态写入点

这次最关键的点,其实不是某个接口路径。

而是:

  • token 写了没有
  • 写的是哪种 token
  • 后面的模块读的是不是同一种 token

很多问题,根子都在这里。

3. 没把登录、菜单、路由、权限看成一条链

它们看起来是四件事,其实在后台系统里通常是一条链。

  • 登录产生 token
  • token 决定权限
  • 权限决定菜单
  • 菜单决定路由
  • 路由决定能不能进页面

一环不对,后面都可能歪。

八、以后怎么少走弯路

以后再遇到这种问题,我觉得可以固定按下面几步来查。

第一步:找触发点

先搞清楚,这条链路是谁触发的:

  • 按钮点击
  • 登录回调
  • 页面初始化
  • 路由跳转

第二步:找状态写入点

重点看:

  • token 有没有写
  • 本地缓存有没有更新
  • 全局状态有没有更新

第三步:找状态消费点

也就是谁在用这些状态:

  • 路由守卫
  • 菜单接口
  • 权限接口
  • 页面初始化逻辑

第四步:把分支判断当成状态分流来看

看到 if/else,不要只想"走了哪一支"。

更重要的是问:

这个分支执行完以后,系统会进入什么状态?

第五步:最后再区分"根因"和"结果"

像下面这些现象:

  • 404
  • 401
  • "令牌不合法"
  • 页面空白

很多时候只是结果,不是根因。

九、这套方法能迁移到别的问题吗

可以,而且很通用。

比如下面这些问题,其实都能用同一套思路:

  • 支付成功但订单状态没更新
  • 表单提交成功但列表没刷新
  • 文件上传成功但页面没变化
  • 切换账号后权限混乱

这些问题表面上各不相同,但本质都很像: 接口成功了,但系统没有进入你以为它会进入的那个状态。

十、最后总结

这次问题最后能解决,不是因为我突然找到了什么神奇接口。 真正关键的是,我搞明白了这件事:

代码里还在执行旧业务逻辑,但当前业务已经不需要它了。

所以这次修复,表面上是在改登录代码,实际上是在做一件更重要的事:

让代码重新对齐真实业务。

如果这篇文章只保留一句话,我会写成这样:

登录问题不要只盯着接口,要先看系统状态有没有真正流转起来。

相关推荐
小小小小宇17 分钟前
大模型打分与采样原理,以及 Pi Agent 核心原理
前端
一位正在转型AI全栈的前端工程师42 分钟前
AI 全栈学习之旅 -Week 5:RAG 知识库问答系统:从零到生产级部署的全栈实践总结
前端·python
光影少年1 小时前
react navite 安卓iOS 打包、签名、环境区分
前端·react native·react.js
coderCN1 小时前
Nodejs 第三十四章 数据库(表达式和函数、子查询和连表)
前端·node.js
ssshooter2 小时前
AI 时代你不能不知道的 git worktree
前端·后端·面试
观测云2 小时前
AI时代的用户访问监测:观测云带你身临其境体验用户与前端UI交互旅程
前端·可观测性·观测云·rum
喵本喵叁肆2 小时前
06-M6-部门过滤与综合研判-从问答机到研判助手
前端·javascript·jquery
TomEval3 小时前
【Web UI 自动化】05 - KDT 模式原理与实现
前端·ui·自动化
南雨北斗3 小时前
vue3项目状态持久化方案Pinia
前端