前端接入统一认证门户:搞定 JWT 鉴权与 Token 过期问题
作为一名前端开发者,最近在做业务系统接入公司统一认证门户的工作。踩了不少坑后,我把这套JWT 鉴权 + Token 自动刷新的完整流程梳理成了一篇实战指南,分享给同样在做单点登录接入的同学。
一、先搞懂:统一认证门户到底在解决什么问题?
以前我们做子系统,都是自己搞一套登录、权限逻辑,用户要记 N 套账号密码,开发也重复造轮子。
现在公司推了统一认证门户:
- 所有子系统都接入这个门户,用户只需要登录一次
- 门户统一管理身份、角色、菜单权限
- 子系统只需要做「验证凭证 + 获取权限」,不用自己管登录
对前端来说,核心就是:处理好门户传过来的 Token,实现无感鉴权和自动续期。
二、完整交互流程:从用户点击到页面渲染
我把官方流程图拆解成了前端视角的 8 步,每一步都对应我们要写的代码逻辑:
- 用户登录门户:用户在统一门户完成登录(账号密码 / 短信 / 扫码)
- 门户加载权限:门户后台查出该用户能访问的子系统和菜单
- 展示子系统入口:门户首页只显示用户有权限的系统图标
- 点击跳转子系统:用户点我们的系统,门户拼接 URL,带上两个关键参数: access_token:短期 JWT(建议≤5 分钟,安全性高) refresh_token:长效凭证(7~30 天,用来续期) 示例:https://your-system.com/login?access_token=xxx&refresh_token=yyy
- 子系统接收请求:前端从 URL 里提取 Token,然后立刻清掉 URL 参数(防止泄露)
- 调用接口验身份:前端调用门户的getUserInfo接口,把access_token放在请求头里验证
- 处理三种校验结果: ✅ Token 有效且有权限 → 正常渲染页面 ⏳ Token 过期 → 用refresh_token刷新后重试 ❌ 用户无权限 → 返回 403 或跳回门户登录页
- 渲染页面:根据返回的菜单权限,控制页面按钮和路由的显示
三、前端核心实现: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
运行

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; }}四、前端安全与体验优化要点
- Token 绝不泄露:URL 参数必须清理,access_token只存在内存 / 加密存储,refresh_token要做好 XSS 防护
- 无感刷新:把刷新逻辑封装在请求拦截器里,用户完全感知不到 Token 过期
- 权限控制:拿到用户菜单后,前端要做路由级和按钮级的权限控制,没权限的入口直接隐藏
- 错误兜底:刷新 Token 也失败时,要友好提示并跳回门户登录,避免白屏
五、总结
这套统一认证方案,本质上是把登录和权限的复杂度收敛到了门户,前端只需要专注做好两件事:
- 处理好 Token 的获取、存储与自动刷新
- 根据门户返回的权限,控制页面的访问与展示
对我们前端开发者来说,既减少了重复造登录轮子的工作量,又能借助 JWT 和 refresh_token 机制,实现安全又流畅的单点登录体验。
交互流程
我会持续更新前端 & Node.js 全栈干货,关注我,一起从入门到精通!
文章版权声明:除非注明,否则均为边学边练网络文章,版权归原作者所有