Flutter/Dart:调用自身内部的函数以重复触发计时器以刷新 JWT 令牌?

如何解决Flutter/Dart:调用自身内部的函数以重复触发计时器以刷新 JWT 令牌?

我不想在每次查询时检查我的 JWT 令牌是否已过期,而是只想在 main 中第一次初始化应用程序时检查它,然后每 55 分钟自动刷新一次。

这是我在小部件树顶部调用的刷新函数

 void main() async {
    await refreshToken()
 };

这里是 refreshToken 代码

  Future<String?> refreshToken() async {

  String? refreshToken =  await getCryptRefresh(); //gets refresh token from an encrypted Box
      final http.Response response = 
      await http.post(Uri.parse('http://example.com/refresh'),headers: <String,String>{'Content-Type': 'application/json; charset=UTF-8'},body: jsonEncode(<String?,dynamic>{
        'email': currentemail,'id': currentuserid,'refreshToken': refreshToken
        }),);

    if (response.body.contains('token')) {
       Map<String,dynamic> refreshMap = json.decode(response.body);
         String token = refreshMap['token'];
           putCryptJWT(token); // stores new token in encrypted Hive Box
               print("token renewed = " + token);
               
                 Timer(Duration(minutes: 55),() {
                     refreshToken();
                 });
          
               return token;
    } else {
            String noresponse = 'responsebody doesnt contain token';
                print(noresponse);
    }
}

Android studio 首先给我一个 null 错误,在 refreshToken() 下有一条红线,并建议进行 nullcheck !。但是一旦我这样做了,我就给了我这个错误

The expression doesn't evaluate to a function,so it can't be invoked.

它建议我删除 getter 调用中的括号。所以我删除了括号和空检查,只是简单的 refreshToken;

但它并没有像我希望的那样每 55 分钟运行一次。

我不想在每次查询时都检查到期时间。我的 JWTToken 和它的 RefreshToken 都存储在一个加密的 Hive 盒中。因此,检查每个查询似乎有点密集。

解决方法

我不建议这样做。你正在为自己创造很多工作。 更好的方法是拦截您的请求的响应。检查响应代码是否为 401(意思是未授权),我猜这是您的后端会返回的。然后刷新令牌,并再次触发原始请求。 这是一种更加无缝的工作方式,因此没有不必要的令牌过期检查,并且用户体验仍然是无缝的。 您可以使用 Dio,包轻松完成此操作。 你可以做这样的事情。

var _http;
void initMethod(){
_http = Dio();
//set some headers
_http.options.contentType = "application/json";
_http.options.headers['Content-Type'] = "application/json";
//Now add interceptors for both request and response to add a token on outgoing request and to handle refresh on failed response.
_http.interceptors
        .add(InterceptorsWrapper(onRequest: (RequestOptions options) async {
      return await _addAuthenticationToken(options);
    },onResponse: (Response response) async {
      if (response.statusCode == 401) return await refreshToken(response);
return response;
    }));
}

Future<Response> refreshtoken(Response response){
//Get your new token here
//Once you have the token,retry the original failed request. (After you set the token where ever you store it etc)
return await _retry(response);
}
Future<RequestOptions> _addAuthenticationToken(RequestOptions options) async {
    
    if (tokenPair != null)
      options.headers['Authorization'] =
          "Bearer " + "yout token goes here";
    return options;
  }

Future<Response<dynamic>> _retry(RequestOptions requestOptions) async {
    final options = new Options(
      method: requestOptions.method,headers: requestOptions.headers,);
    return await this._http.request<dynamic>(requestOptions.path,data: requestOptions.data,queryParameters: requestOptions.queryParameters,options: options);
  }

您可能需要进行试验以检查是否获得了所需的结果,但这应该可以解决问题

,

在某些情况下,您无法从后端获得响应,这就是我的情况。自从我开始获取令牌并继续计数以来,我在应用程序中添加了计数器。您的方法是回复我在不精确之前测试过的 CPU 时钟,有些设备可能计算得更快,有些甚至更慢。我的方法将使用 Date time now 并使用我们在开始时每 15 秒保存的时间戳检查不同的日期时间,因此它仍然不完全准确,但至少错误不应超过 15 秒

DateTime _timeoutAt;

start() {
   _timeoutAt = DateTime.now().add(Duration(minutes: 55);
   Timer _timerCheckIsTimeout = Timer.periodic(Duration(seconds: 15),(timer) {
   final isTimeout = DateTime.now().isAfter(_timeoutAt)
   if (isTimeout) {
      //Call back from here
      await refreshToken();
      timer.cancel();
   }
}

我知道这不是最佳实践,但人们有不同的条件,他们无法提出最佳实践。如果您可以控制后端进行响应,请使用上面的示例。

,

我不知道这是否比使用 Dio 更可取,但我只是对所有 HTTP post 请求这样做;

else if (response.body.contains('TokenExpiredError')) {
     await refreshToken();
       return downloadMainJSON(
        );

它似乎运作良好。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?