dio拦截器 flutter_Flutter开发 Dio拦截器实现token验证过期的功能
前言:之前分享过在Android中使用Retrofit实现token失效刷新的处理方案,现在Flutter项目也有“token验证过期”的需求,所以接下来我简单总结一下在Flutter项目中如何实现自动刷新token并重发请求的拦截器功能,希望对大家有所帮助。思路:1.Dio实现网络请求2.自定义token拦截器,实现token自动刷新并重发请求3.EventBus发送登录失效事件,弹出登录页面实
前言:
之前分享过在Android中使用Retrofit实现token失效刷新的处理方案,现在Flutter项目也有“token验证过期”的需求,所以接下来我简单总结一下在Flutter项目中如何实现自动刷新token并重发请求的拦截器功能,希望对大家有所帮助。
思路:
1.Dio实现网络请求
2.自定义token拦截器,实现token自动刷新并重发请求
3.EventBus发送登录失效事件,弹出登录页面
实现的步骤:
1.配置Android目录的gradle依赖
dependencies {
...
implementation 'de.greenrobot:eventbus:3.0.0-beta1'
}
2.在pubspec.yaml添加sdk
dependencies:
...
cupertino_icons: ^0.1.0
dio: ^2.1.2
event_bus: ^1.0.0
3.封装一个获取新的accessToken方法
Future getToken() async {
String accessToken = DataUtil.getAccessToken; //获取当前的accessToken
String refreshToken = DataUtil.getRefreshToken; //获取当前的refreshToken
Dio dio =DioUtil.getInstance().tokenDio; ////创建新Dio实例
dio.options.headers['x-access-token'] = accessToken;//设置当前的accessToken
try {
String url = url; //refreshToken url
var response = await dio.get(url,options: options); //请求refreshToken刷新的接口
accessToken = response.data['access_token']; //新的accessToken
refreshToken = response.data['refresh_token'];//新的refreshToken
DataUtil.saveRefreshToken(refreshToken); //保存新的refreshToken
} on DioError catch (e) {
if (e.response == null) {
} else {
eventBus.fire(new LoginEvent("Login"));//refreshToken过期,eventBus弹出登录页面
}
}
return accessToken;
}
4.token失效时,异步获取accessToken
onError(DioError error) async {
if (error.response != null && error.response.statusCode == 401) { 401代表token过期
Dio dio = DioUtil().dio;//获取Dio单例
dio.lock();
String accessToken = await getToken(); //异步获取新的accessToken
DataUtil.saveAccessToken(accessToken); //保存新的accessToken
dio.unlock();
}
super.onError(error);
}
5.重新发起一个请求获取数据
//重新发起一个请求获取数据
var request = error.response.request;
try {
var response = await dio.request(request.path,
data: request.data,
queryParameters: request.queryParameters,
cancelToken: request.cancelToken,
options: request,
onReceiveProgress: request.onReceiveProgress);
return response;
} on DioError catch (e) {
return e;
}
6.Dio拦截器的完整代码
class TokenInterceptor extends Interceptor {
@override
onError(DioError error) async {
if (error.response != null && error.response.statusCode == 401) { //401代表token过期
Dio dio = DioUtil().dio;//获取Dio单例
dio.lock();
String accessToken = await getToken(); //异步获取新的accessToken
DataUtil.saveAccessToken(accessToken); //保存新的accessToken
dio.unlock();
//重新发起一个请求获取数据
var request = error.response.request;
try {
var response = await dio.request(request.path,
data: request.data,
queryParameters: request.queryParameters,
cancelToken: request.cancelToken,
options: request,
onReceiveProgress: request.onReceiveProgress);
return response;
} on DioError catch (e) {
return e;
}
}
super.onError(error);
}
Future getToken() async {
String accessToken = DataUtil.getAccessToken; //获取当前的accessToken
String refreshToken = DataUtil.getRefreshToken; //获取当前的refreshToken
Dio dio =DioUtil.getInstance().tokenDio; ////创建新Dio实例
dio.options.headers['x-access-token'] = accessToken;//设置当前的accessToken
try {
String url = url; //refreshToken url
var response = await dio.get(url,options: options); //请求refreshToken刷新的接口
accessToken = response.data['access_token']; //新的accessToken
refreshToken = response.data['refresh_token'];//新的refreshToken
DataUtil.saveRefreshToken(refreshToken); //保存新的refreshToken
} on DioError catch (e) {
if (e.response == null) {
} else {
eventBus.fire(new LoginEvent("Login"));//refreshToken过期,eventBus弹出登录页面
}
}
return accessToken;
}
}
7.添加自定义的token拦截器
/*
*Dio网络请求的工具类
*/
class DioUtil {
Dio dio;
Dio tokenDio = new Dio();
static DioUtil _instance;
static DioUtil getInstance() {
if (_instance == null) {
_instance = DioUtil();
}
return _instance;
}
//get方法
Future get(url, {data, options, cancelToken}) async {
String accessToken = DataUtil.getAccessToken; //获取当前的accessToken
String refreshToken = DataUtil.getRefreshToken; //获取当前的refreshToken
options = BaseOptions(
connectTimeout: 15000,
headers: {},
);
dio = new Dio(options);
//添加自定义的token拦截器
dio.interceptors.add(new TokenInterceptor());
Response response;
try {
response = await dio.get(url, cancelToken: cancelToken);
} on DioError catch (e) {
print(e.response.data);
}
return response;
}
}
8.EventBus发送登录失效事件,弹出登录页面
EventBus eventBus = new EventBus();
//自定义登录的eventBus类
class LoginEvent {
String text;
LoginEvent(this.text);
}
//在登录的页面接受eventBus事件
class LoginPageState extends State {
....
@override
void initState() {
super.initState();
eventBus.on().listen((LoginEvent data) {
//TO DO SOMETHING
});
}
}
9.总结
在Flutter项目中自定义一个自动刷新并重发请求的Dio拦截器,经过不断调试,最终实现了功能。如果有什么疑问的话,欢迎留言联系我哦!
更多推荐



所有评论(0)