前端验证(前端接入统一认证门户:搞定 JWT 鉴权与 Token 过期问题)

前端验证(前端接入统一认证门户:搞定 JWT 鉴权与 Token 过期问题)
前端接入统一认证门户:搞定 JWT 鉴权与 Token 过期问题

作为一名前端开发者,最近在做业务系统接入公司统一认证门户的工作。踩了不少坑后,我把这套JWT 鉴权 + Token 自动刷新的完整流程梳理成了一篇实战指南,分享给同样在做单点登录接入的同学。


一、先搞懂:统一认证门户到底在解决什么问题?

以前我们做子系统,都是自己搞一套登录、权限逻辑,用户要记 N 套账号密码,开发也重复造轮子。

现在公司推了统一认证门户

  • 所有子系统都接入这个门户,用户只需要登录一次
  • 门户统一管理身份、角色、菜单权限
  • 子系统只需要做「验证凭证 + 获取权限」,不用自己管登录

对前端来说,核心就是:处理好门户传过来的 Token,实现无感鉴权和自动续期


二、完整交互流程:从用户点击到页面渲染

我把官方流程图拆解成了前端视角的 8 步,每一步都对应我们要写的代码逻辑:

  1. 用户登录门户:用户在统一门户完成登录(账号密码 / 短信 / 扫码)
  2. 门户加载权限:门户后台查出该用户能访问的子系统和菜单
  3. 展示子系统入口:门户首页只显示用户有权限的系统图标
  4. 点击跳转子系统:用户点我们的系统,门户拼接 URL,带上两个关键参数: access_token:短期 JWT(建议≤5 分钟,安全性高) refresh_token:长效凭证(7~30 天,用来续期) 示例:https://your-system.com/login?access_token=xxx&refresh_token=yyy
  5. 子系统接收请求:前端从 URL 里提取 Token,然后立刻清掉 URL 参数(防止泄露)
  6. 调用接口验身份:前端调用门户的getUserInfo接口,把access_token放在请求头里验证
  7. 处理三种校验结果: ✅ Token 有效且有权限 → 正常渲染页面 ⏳ Token 过期 → 用refresh_token刷新后重试 ❌ 用户无权限 → 返回 403 或跳回门户登录页
  8. 渲染页面:根据返回的菜单权限,控制页面按钮和路由的显示

三、前端核心实现:JWT 鉴权与 Token 自动刷新

1. 提取并清理 URL 参数

用户从门户跳过来时,Token 是挂在 URL 上的,我们第一步要做的就是「拿了就藏」:

javascript

运行

// 从URL解析参数const urlParams = new URLSearchParams_(window.location.search);const accessToken = urlParams.get('access_token');const refreshToken = urlParams.get('refresh_token');// 立刻清除URL参数,防止Token泄露window.history.replaceState({}, document.title, _window.location.pathname);// 把Token存到localStorage或vuex/pinia里localStorage.setItem('access_token', accessToken);localStorage.setItem('refresh_token', refreshToken);

2. 调用获取用户信息接口

这是鉴权的核心一步,要严格按照接口规范来:

  • 接口地址:http://IP:PORT/ems/portal/api/getUserInfo?systemCode=你的系统编码
  • 请求方式:GET
  • 请求头:Authorization: Bearer {access_token}
  • Query 参数:systemCode(必须和门户注册的一致)

示例代码(以 axios 为例):

javascript

运行

前端验证(前端接入统一认证门户:搞定 JWT 鉴权与 Token 过期问题)

import axios from 'axios';const systemCode = 'YOUR_SYSTEM_CODE'; // 从门户获取的系统编码async function getUserInfo() {  const accessToken = localStorage.getItem('access_token');  try {    const res = await axios.get('/ems/portal/api/getUserInfo', {      params: { systemCode },      headers: {        'Content-Type': 'application/json',        'Authorization': `Bearer ${accessToken}`      }    });    // 存储用户信息和权限菜单    return res.data;  } catch (err) {    // 如果是Token过期,进入刷新逻辑    if (err.response?.status === 401) {      return refreshTokenAndRetry();    }    // 其他错误(无权限等)    throw err;  }}

3. Token 过期自动刷新:实现无感续期

access_token只有 5 分钟有效期,用户操作时很容易过期,所以必须做自动刷新

根据最新接口文档,刷新接口规范如下:

  • 接口地址:http://IP:PORT/ems/portal/api/refreshToken
  • 请求方式:GET
  • 请求头:Authorization: Bearer {refresh_token}
  • 无 Query 参数,直接在请求头里传refresh_token

javascript

运行

async function refreshTokenAndRetry() {  const refreshToken = localStorage.getItem('refresh_token');  try {    // 调用刷新Token接口(注意:这里传的是refresh_token)    const res = await axios.get('/ems/portal/api/refreshToken', {      headers: {        'Content-Type': 'application/json',        'Authorization': `Bearer ${refreshToken}`      }    });    const newAccessToken = res.data.access_token;    // 更新本地存储的access_token    localStorage.setItem('access_token', newAccessToken);    // 用新Token重试获取用户信息    return getUserInfo();  } catch (refreshErr) {    // 刷新失败(比如refresh_token也过期了),跳回登录页    _window.location.href = '门户登录地址';    throw refreshErr;  }}

四、前端安全与体验优化要点

  1. Token 绝不泄露:URL 参数必须清理,access_token只存在内存 / 加密存储,refresh_token要做好 XSS 防护
  2. 无感刷新:把刷新逻辑封装在请求拦截器里,用户完全感知不到 Token 过期
  3. 权限控制:拿到用户菜单后,前端要做路由级和按钮级的权限控制,没权限的入口直接隐藏
  4. 错误兜底:刷新 Token 也失败时,要友好提示并跳回门户登录,避免白屏

五、总结

这套统一认证方案,本质上是把登录和权限的复杂度收敛到了门户,前端只需要专注做好两件事:

  • 处理好 Token 的获取、存储与自动刷新
  • 根据门户返回的权限,控制页面的访问与展示

对我们前端开发者来说,既减少了重复造登录轮子的工作量,又能借助 JWT 和 refresh_token 机制,实现安全又流畅的单点登录体验。


交互流程


我会持续更新前端 & Node.js 全栈干货,关注我,一起从入门到精通!

文章版权声明:除非注明,否则均为边学边练网络文章,版权归原作者所有

最新文章

热门文章

本栏目文章