网上查了一圈,没发现有人分享,一路吃坑吃过来,终于实现了自动刷新 token 并重发请求的拦截器。

然后就想着分享一下,也许分享出来可以帮助小伙伴快速实现自己的token刷新机制,关于Dio的拦截器,不过多介绍,直接前往 Dio 的文档,即可找到拦截器的介绍。我只说一下使用上需要注意的点,以及我写的代码。不多,也就70行。

拦截器文档传送门:Dio中文文档

先上拦截器类的整体代码,然后简单讲解一下

import 'dart:async';import 'package:college_circle/data/events/login_Invalid_event.dart';
import 'package:college_circle/data/models/auth.dart';
import 'package:college_circle/data/net/dio_util.dart';
import 'package:college_circle/util/config.dart';
import 'package:college_circle/util/event_manager.dart';
import 'package:dio/dio.dart';class RefreshTokenInterceptor extends Interceptor {@overrideonError(DioError err) async {if (err.response != null && err.response.statusCode == 401 && Auth.isLogin) {Dio dio = DioUtil().getDio(); //获取dio单例dio.lock();Auth.token = await getToken(); //获取新tokenAuth.save();DioUtil().setToken(Auth.token);dio.unlock();var request = err.response.request; //千万不要调用 err.requesttry {var response = await dio.request(request.path,data: request.data,queryParameters: request.queryParameters,cancelToken: request.cancelToken,options: request,onReceiveProgress:request.onReceiveProgress //TODO 差一个onSendProgress);return response;} on DioError catch (e) {return e;}}super.onError(err);}///获取新tokenFuture<String> getToken() async {String token = Auth.token; //获取当前tokenDio ndio = DioUtil.createNewDio(); //创建新dio实例ndio.options.baseUrl = AppConfig.DOMAIN_NAME; //配置baseUrlndio.options.headers['Authorization'] = 'JWT ${token}'; //设置当前tokentry {var response = await ndio.get('/auth/fresh');token = response.data['data']['access_token']; //获取返回的新tokenprint('newToken:$token');} on DioError catch (e) {if (e.response == null) {print('DioError:${e.message}');} else {if (e.response.statusCode == 422) {print('422Error:${e.response.data['msg']}');//422状态码代表异地登录,token失效,发送登录失效事件,以便app弹出登录页面EventManager.get(EventGroup.app).fire(LoginInvalidEvent());}}}return token;}
}复制代码

这里分成两个函数讲解:

getToken

我们后端的 token 验证是检查请求头里的 Authorization 字段。然后能用到期的 token 直接请求新的 token,然后再来看 getToken 函数,这是个异步函数,很简单,就是拿到当前的 token,然后创建一个新的 dio 对象(这里注意一定要创建新的 dio 对象,不要用添加了拦截器的那个 dio 对象,不然会发生死锁,这一点官方文档也有提到)。

然后用新的 dio 对象去请求新的 token,然后把新 token 返回给调用者。这里有个异常处理,处理 token 刷新失败的情况是否为异地登录,然后发送登录失效的事件,这个事件发送是用的 event_bus 插件。超级好用。

onError

这里挺麻烦的,先获取 err 对象的 response 对象,判断状态码是否为 401 ,为 401 则是 token 失效了,需要刷新。在刷新之前,要给拦截器上个锁,这里给 requestLock 给锁上,锁 requestLock 目的是为了防止更多的 401 错误,并且导致重复刷新 token。

然后调用 getToken 获取新 token 然后把新 token 保存起来,再给 DioUtil单例对象的 dio 设置上token,这个单例是平时请求用的。然后把拦截器的锁给解开,这样后面的请求就可以携带上新的token去服务器拿数据了。

接下来是容易出错的请求重发环节,这里要拿到 token 失效的那个请求。留意一段代码var request = err.response.request;

我一开始是调用的 err.request ,结果后续用到 request 变量的地方就报错了,空对象错误,折腾了一会儿才发现要拿到发生错误的请求要用 err.response.request

然后就是重新发起一个请求获取数据了

      try {var response = await dio.request(request.path,data: request.data,queryParameters: request.queryParameters,cancelToken: request.cancelToken,options: request,onReceiveProgress:request.onReceiveProgress //TODO 差一个onSendProgress);return response;} on DioError catch (e) {return e;}复制代码

这里就可以用平时发请求的 dio 对象了,最好用 try...catch 捕获错误,如果发生错误就把错误抛给下一个拦截器。

最后把请求到的结果返回一下就好了。新请求的参数都从之前获取的 request 对象里拿。

代码还有一点瑕疵,但是能正常的运行了,我觉得重发请求那一块还有优化的空间。

转载于:https://juejin.im/post/5c7a3019f265da2d8d69f6cb

flutetr dio 拦截器实现 token 失效刷新相关推荐

  1. vue ajax拦截器,Vue-resource拦截器判断token失效跳转详解

    本文主要为大家带来一篇Vue-resource拦截器判断token失效跳转的实例.小编觉得挺不错的,现在就分享给大家,也给大家做个参考.一起跟随小编过来看看吧,希望能帮助到大家. 在拦截器中设置全局的 ...

  2. dio拦截器 flutter_Flutter开发 Dio拦截器实现token验证过期的功能

    前言: 之前分享过在Android中使用Retrofit实现token失效刷新的处理方案,现在Flutter项目也有"token验证过期"的需求,所以接下来我简单总结一下在Flut ...

  3. OKhttp 拦截器Intercept token失效验证

    转载请说明出处: 前言:我相信现在很多人都在用OKhttp作为网络请求库,为什么OKhttp会受到这么多人的青睐呢,谷歌也不例外(据我了解到它是唯一一个被谷歌认可的第三方网络请求库), 原因有很多,对 ...

  4. angular4 使用HttpClient拦截器 检查token失效,返回登录页面

    1.首先创建一个拦截器服务:InterceptorService.ts 2.在app.module.ts文件里引入拦截器 import {InterceptorService} from './Int ...

  5. 面试宝典三 --学科管理模块(拦截器,token,统一异常处理)

    面试宝典 需求分析 涉及到的表,实体类,页面 学科管理页面跳转 新增学科 分析 前端统一设置拦截器 后台登录拦截配置 统一异常处理 RequestException: 前端新增学科 后端逻辑 Cour ...

  6. 前端学习(2708):重读vue电商网站28之通过axios请求拦截器添加 token

    通过axios请求拦截器添加 token,保证拥有获取数据的权限. 原因是,后台那边除开登录的 api,其它都需要进行授权 . 因此,我们可以利用 axios 中interceptors属性,其中有一 ...

  7. 前端学习(2707):重读vue电商网站27之通过axios请求拦截器添加 token

    通过axios请求拦截器添加 token,保证拥有获取数据的权限. 原因是,后台那边除开登录的 api,其它都需要进行授权 . 因此,我们可以利用 axios 中interceptors属性,其中有一 ...

  8. JWT的API鉴权,基于拦截器的token与鉴权

    基于JWT的API鉴权 基于拦截器的token与鉴权 如果我们每个方法都去写一段代码,冗余度太高,不利于维护,那如何做使我们的代码看起来更清爽呢?我们可以  将这段代码放入拦截器去实现 Spring中 ...

  9. 前后端分离,如何解决跨域(代理模式)、路由拦截(进入页面需要登录)以及请求拦截(登录TOKEN失效)等问题(初学者)

    前端时间项目需要发布一个较大的版本,工作比较忙,加了好多个晚上的班,感觉自己有点缺氧了.最近稍微闲下来了,顺便调休了三天,刚刚给家里来了个大扫除,看着这干干净净的小家,心里顿时舒服了很多. 下面进入正 ...

  10. dio拦截器 flutter_详解flutter之网络请求dio,请求,拦截器简单示例

    flutter一直很火的网络请求插件dio 直接上代码,写成一个类,可以直接使用 包含请求的封装,拦截器的封装 import 'package:dio/dio.dart'; import 'dart: ...

最新文章

  1. JAVA学习日记DAY1
  2. 【鸿蒙 HarmonyOS】HarmonyOS 开发环境搭建 ( Node.js 安装 )
  3. 《openssl编程》之基础知识
  4. vb冒泡排序法流程图_VB算法-冒泡排序教案
  5. 仿QQ校友DIV模拟窗口
  6. 2019 年容器安全最新现状研究报告:意识普遍低,责任归属难!
  7. C- unsigned :1之位域分析
  8. CentOS 6.5 安装 java 环境
  9. 雾霾的结构化责任主体
  10. 大学计算机实验教程实验4,计算机组成原理实验报告(四个实验 图)
  11. 关于USB3.0的U盘正确用法
  12. Loan Repayment//二分//排位3
  13. 倍福 TwinCAT背景知识
  14. MySQL备份还原和定时任务
  15. 数字孪生天然气管道解决方案
  16. 【亲测】独家更新CcPay多商户码支付系统,码支付易支付+个人支付宝微信二维码收款app监控+搭建教程
  17. 雨水情自动监测 遥测终端机
  18. 项目管理涉及到的文档
  19. 基于PHP+MySQL汽车展览会网站的设计与实现
  20. QMUI框架简介,送大厂面经一份

热门文章

  1. 机器人自动化《RPA应用场景和发展趋势》
  2. 报错 xxx@1.0.0 dev D:\ webpack-dev-server --inline --progress --configbuild/webpack.dev.conf.js
  3. WPS入门StackPanel与Grid
  4. docker ssh连接
  5. python实现的 AWGN信道下QPSK调制信号的平均相位估计
  6. 永久使用卡巴斯基的方法
  7. 使用ActivityGroup类显示多个Activity
  8. 中燃料场报表生成器--出库报表
  9. Linux vlan间路由配置,VLAN间路由
  10. Dynamips和Vmware完成CCVP试验(6)