web-dev-qa-db-fra.com

Utilisation d'Interceptor dans Dio for Flutter pour actualiser le jeton

J'essaie d'utiliser Interceptor avec Dio en flutter, je dois gérer l'expiration du jeton. voici mon code

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;
  }

problème est au lieu de répéter l'appel réseau avec le nouveau jeton, Dio renvoie l'objet d'erreur à la méthode d'appel, qui à son tour rend le mauvais widget, des pistes sur la façon de gérer l'actualisation du jeton avec dio?

9
r4jiv007

Je l'ai résolu en utilisant des intercepteurs de la manière suivante: -

  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;
  }
7
r4jiv007

Vous obtiendrez un code d'état de réponse 401 pour l'expiration du jeton. Afin de demander un nouveau jeton d'accès, vous devez utiliser la méthode post avec données de formulaire et les Dio options (type de contenu et en-têtes) requis. Ci-dessous, le code montre comment demander un nouveau jeton.

Une fois la demande réussie, si vous obtenez le code d'état de réponse 200, vous obtiendrez une nouvelle valeur de jeton d'accès ainsi qu'une valeur de jeton d'actualisation et les enregistrerez dans le stockage que vous préférez utiliser. Par exemple, Préférences partagées.

Une fois que vous avez enregistré un nouveau jeton d'accès, vous pouvez l'utiliser pour récupérer des données en utilisant la méthode get indiquée dans le même code ci-dessous.

onError(DioError error) async {
    if (error.response?.statusCode == 401) {
      Response response;
      var authToken = base64
          .encode(utf8.encode("username_value" + ":" + "password_value"));
      FormData formData = new FormData.from(
          {"grant_type": "refresh_token", "refresh_token": refresh_token_value});
      response = await dio.post(
        url,
        data: formData,
        options: new Options(
            contentType: ContentType.parse("application/x-www-form-urlencoded"),
            headers: {HttpHeaders.authorizationHeader: 'Basic $authToken'}),
      );
      if (response.statusCode == 200) {
        response = await dio.get(
          url,
          options: new Options(headers: {
            HttpHeaders.authorizationHeader: 'Bearer access_token_value'
          }),
        );
        return response;
      } else {
        print(response.data);
        return null;
      }
    }
    return error;
  }
4
Venkatesh Raju

Je n'ai pas encore terminé l'implémentation du client Http personnalisé, mais cela peut vous aider.

Http personnalisé

Intercepteur

Principal

2
Lucas Simon