当前位置: 首页 > news >正文

无感刷新Token:如何做到让用户“永不掉线”

无感刷新 Token:平衡安全与用户体验的认证方案

问题背景

当用户操作正投入时,突然出现"登录已过期,请重新登录"的提示,这种突兀的中断会:

  • 破坏用户体验:打断用户操作流程
  • 可能导致数据丢失:未保存的操作可能丢失
  • 降低用户满意度:频繁登录影响使用体验

然而,出于安全考虑,认证 Token 必须有较短的有效期。

核心矛盾:Access Token 的"天生矛盾"

安全要求

  • Access Token 有效期要短(如30分钟)
  • 防止泄露后被长期滥用

用户体验要求

  • 用户不希望频繁重新登录
  • 希望保持持续的登录状态

解决方案:双 Token 认证系统

两种 Token 的作用

Token 类型用途特点存储方式
Access Token访问受保护 API 资源生命周期短(1-2小时)
无状态,服务器无需存储
客户端内存(Vuex/Redux)
Refresh Token获取新的 Access Token生命周期长(7-30天)
有状态,服务器需存储
HttpOnly Cookie(防XSS)

为什么需要 Refresh Token?

  1. 主动吊销能力:Refresh Token 有状态,服务器可主动吊销
  2. 减少密码暴露:无需频繁输入密码
  3. 平衡安全与体验:短期的 Access Token 保证安全,长期的 Refresh Token 保证体验

无感刷新详细工作流程

1. 首次登录

// 用户使用用户名密码登录POST/api/auth/login{"username":"user","password":"password"}// 服务器返回{"access_token":"eyJ...","expires_in":3600,"refresh_token":"rt_..."}

2. 正常请求流程

客户端 → 携带 Access Token → 服务器 客户端 ← 返回请求结果 ← 服务器

3. Token 过期处理流程

1. Access Token 过期 → 请求失败 (401) 2. 拦截 401 错误 → 暂停原始请求 3. 使用 Refresh Token → 请求新 Access Token 4. 刷新成功 → 用新 Token 重试原始请求 5. 刷新失败 → 强制用户重新登录

实战实现:Axios 拦截器方案

1. 创建 Axios 实例

// api/request.jsimportaxiosfrom'axios';constservice=axios.create({baseURL:'/api',timeout:10000,});// 请求拦截器service.interceptors.request.use(config=>{constaccessToken=getAccessTokenFromStore();if(accessToken){config.headers['Authorization']=`Bearer${accessToken}`;}returnconfig;},error=>Promise.reject(error));

2. 核心响应拦截器实现

// api/request.jsletisRefreshing=false;// 刷新状态标志letrequests=[];// 挂起请求队列service.interceptors.response.use(response=>response,asyncerror=>{const{config,response}=error;// 非 401 错误直接返回if(!response||response.status!==401){returnPromise.reject(error);}// 避免重复刷新:如果正在刷新,挂起请求if(isRefreshing){returnnewPromise(resolve=>{requests.push(()=>resolve(service(config)));});}isRefreshing=true;try{// 调用刷新接口const{newAccessToken}=awaitrefreshTokenApi();// 更新本地存储的 tokensetAccessTokenInStore(newAccessToken);// 重试原始请求config.headers['Authorization']=`Bearer${newAccessToken}`;// 执行所有挂起的请求requests.forEach(cb=>cb());requests=[];returnservice(config);}catch(refreshError){// 刷新失败,强制登出logoutUser();returnPromise.reject(refreshError);}finally{isRefreshing=false;}});exportdefaultservice;

关键优化点

1. 并发请求处理

// 使用队列管理并发请求if(isRefreshing){// 将请求加入队列,等待刷新完成returnnewPromise(resolve=>{requests.push(()=>{config.headers['Authorization']=`Bearer${getAccessTokenFromStore()}`;resolve(service(config));});});}

2. 刷新令牌旋转(Token Rotation)

// 每次刷新都生成新的 Refresh TokenconstrefreshTokenApi=async()=>{constresponse=awaitaxios.post('/api/auth/refresh',{},{withCredentials:true// 自动发送 HttpOnly Cookie});return{newAccessToken:response.data.access_token,newRefreshToken:response.data.refresh_token// 可选的令牌旋转};};

3. 防抖处理

// 防止短时间内多次触发刷新letrefreshPromise=null;constrefreshTokenWithDebounce=async()=>{if(!refreshPromise){refreshPromise=refreshTokenApi().finally(()=>{refreshPromise=null;});}returnrefreshPromise;};

安全注意事项

1. Refresh Token 存储安全

  • 必须使用 HttpOnly Cookie:防止 XSS 攻击窃取
  • 设置 Secure 标志:仅通过 HTTPS 传输
  • 设置 SameSite 策略:防止 CSRF 攻击

2. 令牌管理策略

// 服务器端 Refresh Token 管理constrefreshTokenStore={// 记录有效的 Refresh TokenvalidTokens:newMap(),// 添加新令牌addToken(userId,token,deviceInfo){this.validTokens.set(token,{userId,deviceInfo,createdAt:Date.now()});},// 吊销令牌revokeToken(token){this.validTokens.delete(token);},// 吊销用户所有令牌revokeAllUserTokens(userId){for(const[token,info]ofthis.validTokens){if(info.userId===userId){this.validTokens.delete(token);}}}};

3. 过期时间配置建议

// 合理的过期时间配置consttokenConfig={accessToken:{expiresIn:'1h',// 1小时,平衡安全与刷新频率type:'JWT'},refreshToken:{expiresIn:'7d',// 7天,避免永久登录maxAge:30*24*60*60*1000// Cookie 30天}};

错误处理与用户体验

1. 优雅降级策略

consthandleTokenRefresh=async()=>{try{returnawaitrefreshTokenApi();}catch(error){// 根据错误类型处理switch(error.response?.status){case403:// Refresh Token 无效,需重新登录showToast('会话已过期,请重新登录');redirectToLogin();break;case429:// 请求过于频繁showToast('操作过于频繁,请稍后重试');break;default:// 网络或其他错误showToast('网络异常,请检查连接');}throwerror;}};

2. 用户体验优化

// 添加加载状态提示letshowLoading=false;// 在刷新时显示轻微提示if(!showLoading&&isRefreshing){showLoading=true;showSubtleNotification('正在保持连接...');}

总结

无感刷新 Token 机制是现代 Web 应用的必备功能,它:

  1. 平衡安全与体验:短期 Access Token 保证安全,长期 Refresh Token 保证体验
  2. 实现无缝认证:用户无需感知认证过程
  3. 提升数据安全:支持令牌吊销和细粒度控制
  4. 优化并发处理:智能管理多请求场景

通过合理的设计和实现,可以在不牺牲安全性的前提下,为用户提供"永不掉线"的流畅体验。

http://www.jsqmd.com/news/360585/

相关文章:

  • abp数据库迁记录
  • 2026年污水处理药剂厂家TOP10推荐:聚焦水处理药剂实力品牌,蓝淼环保领衔区域服务标杆 - 深度智识库
  • 2026年烟囱防腐施工优质厂家盘点与选择指南 - 2026年企业推荐榜
  • 法护两节 情暖职工!福州市总工会“两节”普法嘉年华活动圆满举办 - 速递信息
  • 金源木业口碑靠谱吗,在哈尔滨定制包装价格多少钱? - myqiye
  • 2026年湖北景观工程设计服务商首选推荐:中美丽岛景观有限公司 - 2026年企业推荐榜
  • 2026年3+1国际本科安全问题探讨,申请流程全知道 - 工业品牌热点
  • 木制包装箱怎么选择,哈尔滨金源木业是靠谱生产商吗? - 工业品牌热点
  • 分析城市管网运维公司,河北雄安未来之城市政服务费用合理 - mypinpai
  • AI开发-python-langchain框架(1-13 返回xml-格式解析器)
  • ABB ACS510 变频器恒压供水与昆仑通泰触摸屏 485 通讯实现
  • 讲讲广州箱包肩带板扣五金定制供应商排名,哪家更值得合作 - 工业推荐榜
  • 2026年昆明挂坠采购全攻略:从源头到精工的厂家评测 - 2026年企业推荐榜
  • JS Number 精度丢失问题
  • 2026年昆明花园旅居深度测评:六家宝藏酒店谁是你的心头好? - 2026年企业推荐榜
  • 有哪些好用的AI写论文的工具?6款写论文的AI工具,知网查重一把通过无忧! - 掌桥科研-AI论文写作
  • 2026年徐州地区高评价铝基中间合金厂家盘点 - 2026年企业推荐榜
  • 抗真菌洗发水推荐:从根源解决脂溢性皮炎头屑 - 博客万
  • 2026年板式换热器价格大揭秘,扬州镇江地区品牌厂家哪家好 - myqiye
  • 脂溢性皮炎洗发水使用建议:频率与时长 - 博客万
  • 2026年青少年普法宣教展厅建设品牌企业价格大揭秘 - 工业推荐榜
  • 分析来图定制的丝杠厂家,数控设备丝杠供应商怎么选择 - 工业设备
  • 数字广播纽格立NGA-602 DRM数字广播专业监测接收机中波台站数字化改造适用
  • 2026年好用的酿酒降温304不锈钢全自动晾床厂家推荐 - mypinpai
  • 盘点2026年性价比高的PVC防静电地板加工厂,珠海地区推荐 - 工业品网
  • 数字广播媒体服务器NGA-101 DRM媒体编码器广播中波广播站数字化改造适用
  • 参考文献崩了?AI论文工具 千笔ai写作 VS PaperRed,本科生写论文更轻松!
  • 【控制】基于MPC模型预测控制和稀疏识别非线性动力学算法辨识旋翼飞行器的动力学模型附Matlab代码
  • 对比一圈后,一键生成论文工具,千笔·专业学术智能体 VS Checkjie
  • 二硫化硒洗发水选购指南:浓度、品牌、用法全解析 - 博客万