news 2026/5/9 2:30:50

登录获取token和刷新token两个接口是怎么用的???

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
登录获取token和刷新token两个接口是怎么用的???

登录获取 Token 和刷新 Token 是两个配合使用的接口,下面是完整的使用流程和代码实现。

一、两个接口的作用

接口类型使用时机返回内容有效期
登录接口用户首次登录accessToken + refreshTokenaccessToken 短期(如30分钟)
refreshToken 长期(如7天)
刷新Token接口accessToken 过期时新的 accessToken + 新的 refreshToken(可选)重新计时

二、完整流程图

用户登录 ↓ 调用登录接口 → 获取 accessToken + refreshToken ↓ 存储到本地 ↓ 正常请求业务接口(携带 accessToken) ↓ ┌─────────────────┐ │ 接口返回401过期?│ └─────────────────┘ ↓ 是 调用刷新Token接口(携带 refreshToken) ↓ 获取新的 accessToken ↓ 更新本地存储 ↓ 重试刚才失败的请求 ↓ 继续正常请求...

三、完整代码实现

1. 定义 API 接口

// api/auth.jsconstBASE_URL='https://your-api.com';exportdefault{// 登录接口login(data){returnuni.request({url:`${BASE_URL}/login`,method:'POST',data:data});},// 刷新Token接口refreshToken(refreshToken){returnuni.request({url:`${BASE_URL}/refresh`,method:'POST',data:{refreshToken:refreshToken}});}};

2. 登录逻辑

// pages/login/login.vueexportdefault{data(){return{username:'',password:''}},methods:{asynchandleLogin(){try{// 1. 调用登录接口constres=awaitthis.$api.login({username:this.username,password:this.password});if(res.code===0){const{accessToken,refreshToken,expiresIn,tokenType}=res.data;// 2. 存储Tokenthis.saveToken({accessToken,refreshToken,expiresIn,// 有效期时长(毫秒)tokenType// Bearer 或 null});// 3. 跳转到首页uni.switchTab({url:'/pages/index/index'});}else{uni.showToast({title:res.msg||'登录失败',icon:'none'});}}catch(error){console.error('登录失败',error);}},// 存储TokensaveToken(tokenData){constnow=Date.now();// 存储基础信息uni.setStorageSync('accessToken',tokenData.accessToken);uni.setStorageSync('refreshToken',tokenData.refreshToken);uni.setStorageSync('tokenType',tokenData.tokenType||'');// 计算过期时间(绝对时间戳)if(tokenData.expiresIn){uni.setStorageSync('expiresTime',now+tokenData.expiresIn);}elseif(tokenData.expiresTime){uni.setStorageSync('expiresTime',tokenData.expiresTime);}}}};

3. 刷新Token逻辑

// utils/refreshToken.js// 防止多个请求同时刷新Token(锁机制)letisRefreshing=false;letrefreshSubscribers=[];// 待刷新期间缓存的请求functionsubscribeTokenRefresh(callback){refreshSubscribers.push(callback);}functiononTokenRefreshed(newToken){refreshSubscribers.forEach(callback=>callback(newToken));refreshSubscribers=[];}// 刷新TokenasyncfunctionrefreshAccessToken(){try{constrefreshToken=uni.getStorageSync('refreshToken');if(!refreshToken){// 没有refreshToken,跳转登录redirectToLogin();returnnull;}// 调用刷新接口constres=awaituni.request({url:'https://your-api.com/refresh',method:'POST',data:{refreshToken:refreshToken}});if(res.statusCode===200&&res.data.code===0){const{accessToken,refreshToken:newRefreshToken,expiresIn}=res.data.data;// 更新存储uni.setStorageSync('accessToken',accessToken);uni.setStorageSync('expiresTime',Date.now()+expiresIn);// 如果返回了新的refreshToken(通常刷新接口也会返回新的)if(newRefreshToken){uni.setStorageSync('refreshToken',newRefreshToken);}// 通知所有等待的请求onTokenRefreshed(accessToken);returnaccessToken;}else{// 刷新失败,清空Token并跳转登录clearTokenAndRedirect();returnnull;}}catch(error){console.error('刷新Token失败',error);clearTokenAndRedirect();returnnull;}finally{isRefreshing=false;}}// 跳转登录页functionredirectToLogin(){clearToken();uni.reLaunch({url:'/pages/login/login'});}// 清空TokenfunctionclearToken(){uni.removeStorageSync('accessToken');uni.removeStorageSync('refreshToken');uni.removeStorageSync('expiresTime');uni.removeStorageSync('tokenType');}// 导出刷新方法export{refreshAccessToken,clearToken,redirectToLogin};

4. 请求拦截器(自动处理Token过期)

// utils/request.jsimport{refreshAccessToken,redirectToLogin}from'./refreshToken.js';// 请求队列(存放过期期间等待的请求)letrequestQueue=[];letisRefreshing=false;// 发起请求的核心方法functionrequest(config){returnnewPromise((resolve,reject)=>{// 1. 检查Token是否过期constexpiresTime=uni.getStorageSync('expiresTime');constnow=Date.now();// 判断是否需要刷新Tokenif(expiresTime&&now>=expiresTime){// Token已过期,需要刷新if(!isRefreshing){isRefreshing=true;// 刷新TokenrefreshAccessToken().then(newToken=>{if(newToken){// 刷新成功,执行队列中的请求requestQueue.forEach(cb=>cb(newToken));requestQueue=[];// 重新发起当前请求doRequest(config).then(resolve).catch(reject);}else{reject({message:'Token刷新失败'});}isRefreshing=false;}).catch(()=>{isRefreshing=false;reject({message:'Token刷新失败'});});}// 将当前请求加入队列,等刷新完成后重试requestQueue.push((newToken)=>{// 更新config中的tokenconfig.header=getAuthHeader(newToken);doRequest(config).then(resolve).catch(reject);});}else{// Token未过期,直接发起请求config.header=getAuthHeader();doRequest(config).then(resolve).catch(reject);}});}// 实际发起请求functiondoRequest(config){returnnewPromise((resolve,reject)=>{uni.request({url:config.url,method:config.method||'GET',data:config.data,header:config.header,success:(res)=>{// 处理业务错误(如Token无效)if(res.data&&res.data.code===401){// Token无效,强制刷新refreshAccessToken().then(()=>{// 重试请求request(config).then(resolve).catch(reject);}).catch(()=>{redirectToLogin();reject({message:'登录已过期'});});}else{resolve(res);}},fail:(err)=>{reject(err);}});});}// 获取认证请求头functiongetAuthHeader(customToken=null){consttoken=customToken||uni.getStorageSync('accessToken');consttokenType=uni.getStorageSync('tokenType');if(tokenType==='Bearer'){return{'Authorization':`Bearer${token}`};}else{return{'accessToken':token};}}exportdefaultrequest;

5. 实际使用示例

// 在 main.js 中全局挂载importrequestfrom'@/utils/request.js';Vue.prototype.$request=request;// 在页面中使用// pages/index/index.vueexportdefault{asyncmounted(){try{// 自动处理Token过期和刷新constres=awaitthis.$request({url:'https://your-api.com/user/info',method:'GET'});console.log('用户信息:',res.data);}catch(error){console.error('请求失败:',error);if(error.message==='登录已过期'){// 跳转到登录页uni.navigateTo({url:'/pages/login/login'});}}}};

四、关键点总结

1. 刷新策略

  • 主动刷新:每次请求前检查,剩余时间 < 5分钟就提前刷新
  • 被动刷新:请求返回401时触发刷新

2. 并发控制(重要)

// 避免短时间内多次刷新TokenletisRefreshing=false;// 锁标志letrequestQueue=[];// 等待队列

3. 刷新时机

// 在请求拦截器中判断constexpiresTime=uni.getStorageSync('expiresTime');consttimeRemaining=expiresTime-Date.now();if(timeRemaining<5*60*1000){// 剩余不足5分钟awaitrefreshAccessToken();// 提前刷新}

4. Token失效后处理

// 刷新接口也返回401时,清空所有Token并跳转登录if(res.statusCode===401){uni.removeStorageSync('accessToken');uni.removeStorageSync('refreshToken');uni.reLaunch({url:'/pages/login/login'});}

五、注意事项

  1. refreshToken 也有有效期,通常比 accessToken 长(如7天、30天),过期后需要重新登录
  2. 刷新接口也要做防抖,避免短时间内多次调用
  3. 存储到本地时建议加密(特别是 refreshToken)
  4. 登出时要同时清空accessToken 和 refreshToken
  5. 刷新Token接口建议使用 POST 请求,并将 refreshToken 放在 Body 中

按照以上方案实现,就能完美处理 Token 的获取和自动刷新了。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/9 2:30:43

AndroidClaw:基于LLM与无障碍服务的手机端AI智能体开发实践

1. 项目概述&#xff1a;一个运行在手机上的AI“操作员” 最近在捣鼓一个挺有意思的东西&#xff0c;我把它叫做“AndroidClaw”。简单来说&#xff0c;这是一个直接运行在你安卓手机上的AI智能体。它的核心目标&#xff0c;是让大语言模型&#xff08;LLM&#xff09;能真正“…

作者头像 李华
网站建设 2026/5/9 2:30:39

企业微信API实战:自动化创建部门、批量导入成员与消息推送

前言 企业微信提供了完善的API接口&#xff0c;可以实现部门管理、成员管理、消息推送等自动化操作。很多企业的痛点是&#xff1a;员工入职流程靠手动&#xff0c;部门调整靠Excel导入&#xff0c;通知靠人工转发。 这篇用Python代码实现三个常见场景&#xff1a;自动创建部…

作者头像 李华
网站建设 2026/5/9 2:28:53

静态博客生成器实战:从Jekyll到GitHub Pages的极简博客搭建

1. 项目概述&#xff1a;一个极简高效的静态博客生成器 如果你厌倦了WordPress的臃肿、Hexo的复杂配置&#xff0c;或者只是想找一个能让你专注于写作&#xff0c;而不是折腾环境的博客工具&#xff0c;那么你很可能已经听说过或者正在寻找类似 lofder/lofder.github.io 这样…

作者头像 李华
网站建设 2026/5/9 2:28:47

推荐1款Word文档题库转Excel表格,搜题刷题神器!

聊一聊现在上个班不容易。没事还要考一考你。考你不算&#xff0c;还要你准备题&#xff0c;考其他人。网上下载的全是word文档格式的。查看起来太麻烦了。今天分享2个小工具&#xff0c;可以将word文档题库转成excel格式并查看。软件介绍1.Word题库转Excel这是我们下载的word文…

作者头像 李华
网站建设 2026/5/9 2:28:21

BurnOver:智能配额代理解决LLM订阅服务的心跳与配额管理难题

1. 项目概述&#xff1a;BurnOver&#xff0c;一个为订阅制LLM服务设计的智能配额代理 如果你正在使用OpenClaw这类AI智能体框架&#xff0c;并且订阅了像Synthetic.new这样提供固定请求次数&#xff08;比如135次/5小时&#xff09;的LLM服务&#xff0c;那你很可能遇到过两个…

作者头像 李华
网站建设 2026/5/9 2:28:12

解析器传感器在工业自动化中的关键应用与误差控制

1. 解析器传感器在工业应用中的核心价值解析器传感器作为电机位置检测的关键元件&#xff0c;其工作原理基于电磁感应原理。当励磁绕组&#xff08;转子&#xff09;通入高频交流电时&#xff0c;定子上的正弦和余弦绕组会感应出与转子角度相关的电压信号。这种模拟输出特性使其…

作者头像 李华