[英]Flutter: How to refresh token when token expires with ferry (graphql) client?
[英]Flutter: How to Refresh token when token expires during http call?
我是 flutter 的新手,我正在使用http package 进行网络呼叫。 如果请求的响应代码为 200,我想刷新令牌并再次调用请求。如何使用 http package 来实现这一点? 我听说过dio package 但对我来说很复杂。
User getUser(){
final response = http.post(Uri.https(BASE_URL, '/api/user'),
headers: {'Authorization: Bearer $token'});
if(response.statusCode == 200){
return User.fromJson(jsonDecode(response.body)['user']);
}
else if(response.statusCode == 401){
//refresh token and call getUser again
}
}
您可以按如下方式使用刷新令牌:
User getUser(){
final response = http.post(Uri.https(BASE_URL, '/api/user'),
headers: {'Authorization: Bearer $token'});
if(response.statusCode == 200){
return User.fromJson(jsonDecode(response.body)['user']);
}
else if(response.statusCode == 401){
//refresh token and call getUser again
final response = http.post(Uri.https(BASE_URL, '/api/[YourAuthorizationEndpoint]'),
headers: {'grant_type': 'refresh_token', 'refresh_token': '$refresh_token'});
token = jsonDecode(response.body)['token'];
refresh_token = jsonDecode(response.body)['refresh_token'];
return getUser();
}
}
您可以使用 dart 的http/retry
package:
import 'package:http/http.dart' as http;
import 'package:http_retry/http_retry.dart';
final client = RetryClient(
http.Client(),
retries: 1,
when: (response) {
return response.statusCode == 401 ? true : false;
},
onRetry: (req, res, retryCount) {
if (retryCount == 0 && res?.statusCode == 401) {
// refresh token
}
},
);
try {
final response = await client.get('http://www.example.com');
} finally {
client.close();
}
您可以使用Dio Package并创建一个客户端 Class 并从那里管理所有请求。 在这里,我已经完成了 DIO package。
class DioClient {
final String baseUrl;
Dio _dio = new Dio();
DioClient(
this.baseUrl,
) {
_dio
..options.baseUrl = baseUrl
..options.connectTimeout = _defaultConnectTimeout
..options.receiveTimeout = _defaultReceiveTimeout
..httpClientAdapter
..options.responseType = ResponseType.json
if (kDebugMode) {
_dio.interceptors.add(LogInterceptor(
responseBody: true,
error: true,
requestHeader: false,
responseHeader: false,
request: false,
requestBody: false));
}
}
Future<Response> get(
String uri, {
Map<String, dynamic> queryParameters,
Options options,
CancelToken cancelToken,
ProgressCallback onReceiveProgress,
}) async {
try {
var response = await _dio.get(
uri,
queryParameters: queryParameters,
options: options,
cancelToken: cancelToken,
onReceiveProgress: onReceiveProgress,
);
return response;
} on SocketException catch (e) {
throw SocketException(e.toString());
} on FormatException catch (_) {
throw FormatException("Unable to process the data");
} catch (error) {
if (error is DioError) {
switch (error.response.statusCode) {
case 401:
return await DioConnectivityRetrier(
dio: _dio, requestOptions: error.request)
.requestRetrier();
break;
default:
throw error;
break;
}
} else {
throw error;
}
}
}
Future<dynamic> post(
String uri, {
data,
Map<String, dynamic> queryParameters,
Options options,
CancelToken cancelToken,
ProgressCallback onSendProgress,
ProgressCallback onReceiveProgress,
}) async {
try {
var response = await _dio.post(
uri,
data: data,
queryParameters: queryParameters,
options: options,
cancelToken: cancelToken,
onSendProgress: onSendProgress,
onReceiveProgress: onReceiveProgress,
);
return response;
} on FormatException catch (_) {
throw FormatException("Unable to process the data");
} catch (error) {
if (error is DioError) {
switch (error.response.statusCode) {
case 401:
return await DioConnectivityRetrier(
dio: _dio, requestOptions: error.request)
.requestRetrier();
break;
default:
throw error;
break;
}
} else {
throw error;
}
throw error;
}
}
Future<Response> delete(
String uri, {
Map<String, dynamic> queryParameters,
Map<String, dynamic> data,
Options options,
CancelToken cancelToken,
ProgressCallback onReceiveProgress,
}) async {
try {
var response = await _dio.delete(uri,
queryParameters: queryParameters,
options: options,
cancelToken: cancelToken,
data: data);
return response;
} on SocketException catch (e) {
throw SocketException(e.toString());
} on FormatException catch (_) {
throw FormatException("Unable to process the data");
} catch (error) {
if (error is DioError) {
switch (error.response.statusCode) {
case 401:
return await DioConnectivityRetrier(
dio: _dio, requestOptions: error.request)
.requestRetrier();
break;
default:
throw error;
break;
}
} else {
throw error;
}
}
}
}
这是DioConnectivityRetrier class,所以每当您从 API 获得 401 状态时,我们的请求都会调用此 class。 我们可以使用相同的请求数据调用相同的 API 并获取数据。 这里
class DioConnectivityRetrier {
final RequestOptions requestOptions;
final Dio dio;
BuildContext context;
DioConnectivityRetrier({this.requestOptions, this.dio,this.context});
Future<Response> requestRetrier() async {
print('*** request retrier called');
await APIService()
.refreshToken()
.catchError((error) => throw error);
requestOptions.headers = {
'Authorization': 'Bearer ${UserAccess.token}',
};
print('new token->' + UserAccess.token);
try {
return await dio.request(requestOptions.path,
options: requestOptions,
data: requestOptions.data,
cancelToken: requestOptions.cancelToken,
onReceiveProgress: requestOptions.onReceiveProgress,
onSendProgress: requestOptions.onReceiveProgress,
queryParameters: requestOptions.queryParameters);
} catch (e) {
throw NetworkExceptions.getDioException(e);
}
}
}
你可以像这样使用它
DioClient _dioClient = new DioClient(AppConstant.baseUrl);
Response response = await _dioClient.post(apiUrl, data: data).catchError((error) => throw error);
到期后调用 api 刷新令牌
你可以使用这个[包][1]
[1]: https://pub.dev/packages/jwt_decoder检查令牌是否过期
您还可以获得自令牌创建以来的时间和到期日期
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.