我正在try 使用带有Dio的拦截器,我必须处理令牌过期. 以下是我的代码

Future<Dio> getApiClient() async {
    token = await storage.read(key: USER_TOKEN);
    _dio.interceptors.clear();
    _dio.interceptors
        .add(InterceptorsWrapper(onRequest: (RequestOptions options) {
      // Do something before request is sent
      options.headers["Authorization"] = "Bearer " + token;
      return options;
    },onResponse:(Response response) {
        // Do something with response data
        return response; // continue
    }, onError: (DioError error) async {
      // Do something with response error
      if (error.response?.statusCode == 403) {
        // update token and repeat
        // Lock to block the incoming request until the token updated

        _dio.interceptors.requestLock.lock();
        _dio.interceptors.responseLock.lock();
        RequestOptions options = error.response.request;
        FirebaseUser user = await FirebaseAuth.instance.currentUser();
        token = await user.getIdToken(refresh: true);
        await writeAuthKey(token);
        options.headers["Authorization"] = "Bearer " + token;

        _dio.interceptors.requestLock.unlock();
        _dio.interceptors.responseLock.unlock();
        _dio.request(options.path, options: options);
      } else {
        return error;
      }
    }));
    _dio.options.baseUrl = baseUrl;
    return _dio;
  }

问题是,Dio没有使用新令牌重复网络调用,而是将错误对象返回给调用方法,而调用方法又呈现了错误的小部件,有关于如何使用dio处理令牌刷新的线索吗?

推荐答案

我用拦截器解决了这个问题,方法如下:-

  Future<Dio> getApiClient() async {
    token = await storage.read(key: USER_TOKEN);
    _dio.interceptors.clear();
    _dio.interceptors
        .add(InterceptorsWrapper(onRequest: (RequestOptions options) {
      // Do something before request is sent
      options.headers["Authorization"] = "Bearer " + token;
      return options;
    },onResponse:(Response response) {
        // Do something with response data
        return response; // continue
    }, onError: (DioError error) async {
      // Do something with response error
      if (error.response?.statusCode == 403) {
        _dio.interceptors.requestLock.lock();
        _dio.interceptors.responseLock.lock();
        RequestOptions options = error.response.request;
        FirebaseUser user = await FirebaseAuth.instance.currentUser();
        token = await user.getIdToken(refresh: true);
        await writeAuthKey(token);
        options.headers["Authorization"] = "Bearer " + token;

        _dio.interceptors.requestLock.unlock();
        _dio.interceptors.responseLock.unlock();
        return _dio.request(options.path,options: options);
      } else {
        return error;
      }
    }));
    _dio.options.baseUrl = baseUrl;
    return _dio;
  }

DIO 4.0.0支持

    dio.interceptors.add(
          InterceptorsWrapper(
            onRequest: (request, handler) {
              if (token != null && token != '')
                request.headers['Authorization'] = 'Bearer $token';
              return handler.next(request);
            },
            onError: (e, handler) async {
              if (e.response?.statusCode == 401) {
                try {
                  await dio
                      .post(
                          "https://refresh.api",
                          data: jsonEncode(
                              {"refresh_token": refreshtoken}))
                      .then((value) async {
                    if (value?.statusCode == 201) {
                      //get new tokens ...
                      print("access token" + token);
                      print("refresh token" + refreshtoken);
                      //set bearer
                      e.requestOptions.headers["Authorization"] =
                          "Bearer " + token;
                      //create request with new access token
                      final opts = new Options(
                          method: e.requestOptions.method,
                          headers: e.requestOptions.headers);
                      final cloneReq = await dio.request(e.requestOptions.path,
                          options: opts,
                          data: e.requestOptions.data,
                          queryParameters: e.requestOptions.queryParameters);
    
                      return handler.resolve(cloneReq);
                    }
                    return e;
                  });
                  return dio;
                } catch (e, st) {
                  
                }
              }
           },
        ),
    );

Flutter相关问答推荐

我有一个代码因flatter安全性为零而出错

如何防止alert 对话框在收到通知时出现在某个flutter页面中

从Flutter应用程序解释蓝牙BLE数据:了解Sylvania压力值

Build.gradle专线:2个Flutter Flutter

如何实现Flutter 梳理机图像的小量移动

我有相关的下拉菜单Flutter Windows应用程序的问题

在Flutter 中更改扩展瓷砖的高度

如何在Date Time类中只显示日期?

Flutter如何将2个以上的值传递到ListView上的另一个屏幕?

从Firestore流式传输单个文档还是整个集合更好?

如果其他Provider 的帐户已存在,如何阻止用户登录?

Flutter列顶部和底部出现不必要的边距问题

像图像一样Flutter 自定义标签

如何将行推到列的底部

Flutter Bloc 使用 Cubit 监听流和emits 状态

Flutter snapShot.hasData 为假但响应有数据

无法在 flutter 中更新 void 方法内的变量值

如何使用列Flutter 中文本占用的空间来控制svg宽度

我想在数组中添加项目

Flutter Bloc Todo 示例 - 收听存储库中的单个 todo