Old iron remember to forward, Brother Mao will present more Flutter good articles~~~~
WeChat group ducafecat
b Station https://space.bilibili.com/404904528
original
https://medium.com/@wmnkrishanmadushanka/how-to-handle-401-unauthorised-with-dio-interceptor-flutter-60398a914406
reference
- https://pub.dev/packages/dio/versions/4.0.0
- https://pub.dev/packages/flutter_secure_storage
- https://pub.dev/packages/shared_preferences
text
In this article, I will explain how to use flutter dio (4.0.0) to make network calls, and how to use refresh tokens and access tokens in your flutter app to handle 401 when authorizing.
Before reading this article, I hope that you have a basic understanding of shaking mobile application development.
Basic Authentication flow with refresh and access tokens
As you can see in the above figure, it is obvious what is the flow when refresh and access token are used in the authentication flow. After logging in, you will get two flags called refresh and access. This access token expires quickly (the refresh token also expires, but it will take more time than the access token). When you make a request with an expired access token, the status code 401 (Unauthorized) will appear in the response. In this case, you must request a new token from the server and make the previous request again with a valid access token. If the refresh token has also expired, you must instruct the user to log in to the page and force to log in again.
Dio class
class DioUtil {
static Dio _instance;//method for getting dio instance Dio getInstance() {
if (_instance == null) {
_instance = createDioInstance();
}
return _instance;
}
Dio createDioInstance() {
var dio = Dio();// adding interceptor dio.interceptors.clear();
dio.interceptors.add(InterceptorsWrapper(onRequest: (options, handler) {
return handler.next(options);
}, onResponse: (response, handler) {
if (response != null) {
return handler.next(response);
} else {
return null;
}
}, onError: (DioError e, handler) async {
if (e.response != null) {
if (e.response.statusCode == 401) {//catch the 401 here
dio.interceptors.requestLock.lock();
dio.interceptors.responseLock.lock();
RequestOptions requestOptions = e.requestOptions;
await refreshToken();
Repository repository = Repository();
var accessToken = await repository.readData("accessToken");
final opts = new Options(method: requestOptions.method);
dio.options.headers["Authorization"] = "Bearer " + accessToken;
dio.options.headers["Accept"] = "*/*";
dio.interceptors.requestLock.unlock();
dio.interceptors.responseLock.unlock();
final response = await dio.request(requestOptions.path,
options: opts,
cancelToken: requestOptions.cancelToken,
onReceiveProgress: requestOptions.onReceiveProgress,
data: requestOptions.data,
queryParameters: requestOptions.queryParameters);
if (response != null) {
handler.resolve(response);
} else {
return null;
}
} else {
handler.next(e);
}
}
}));
return dio;
}
static refreshToken() async {
Response response;
Repository repository = Repository();
var dio = Dio();
final Uri apiUrl = Uri.parse(BASE_PATH + "auth/reIssueAccessToken");
var refreshToken = await repository.readData("refreshToken");
dio.options.headers["Authorization"] = "Bearer " + refreshToken;
try {
response = await dio.postUri(apiUrl);
if (response.statusCode == 200) {
LoginResponse loginResponse =
LoginResponse.fromJson(jsonDecode(response.toString()));
repository.addValue('accessToken', loginResponse.data.accessToken);
repository.addValue('refreshToken', loginResponse.data.refreshToken);
} else {
print(response.toString()); //TODO: logout
}
} catch (e) {
print(e.toString()); //TODO: logout
}
}
}
The above is the complete course, I will explain the most important part of it.
Mainly, as you can see in the createDioInstance method, you must add an interceptor to catch the 401. When 401 occurs in error: (DioError e, handler) async {} is called. So in your heart
- Check the error code(401), Check the error code(401),
- Get new access token Get new access token
await refreshToken();
The above code will call the refreshToken method and store the new refresh and access tokens in the repository. (For storage repositories, you can use secure storage or shared preferences)
- Copy the previous request and set a new access token
RequestOptions requestOptions = e.requestOptions;
Repository repository = Repository();
var accessToken = await repository.readData("accessToken");
final opts = new Options(method: requestOptions.method);
dio.options.headers["Authorization"] = "Bearer " + accessToken;
dio.options.headers["Accept"] = "*/*";
- Make the previous call again
final response = await dio.request(requestOptions.path,
options: opts,
cancelToken: requestOptions.cancelToken,
onReceiveProgress: requestOptions.onReceiveProgress,
data: requestOptions.data,
queryParameters: requestOptions.queryParameters);
Once you receive a reply, call
handler.resolve(response);
Then the response will be sent to the place where you called the api as shown below.
var dio = DioUtil().getInstance();
final String apiUrl = (BASE_PATH + "payments/addNewPayment/");
var accessToken = await repository.readData("accessToken");
dio.options.headers["Authorization"] = "Bearer " + accessToken;
dio.options.headers["Accept"] = "*/*";//response will be assigned to response variable
response = await dio.post(apiUrl, data: event.paymentRequest.toJson());
Thats all. happy coding :)
© Cat brother
Past
Open source
GetX Quick Start
https://github.com/ducafecat/getx_quick_start
News client
https://github.com/ducafecat/flutter_learn_news
strapi manual translation
WeChat discussion group ducafecat
Series collection
Translation
https://ducafecat.tech/categories/%E8%AF%91%E6%96%87/
Open source project
https://ducafecat.tech/categories/%E5%BC%80%E6%BA%90/
Dart programming language basics
https://space.bilibili.com/404904528/channel/detail?cid=111585
Getting started with Flutter zero foundation
https://space.bilibili.com/404904528/channel/detail?cid=123470
Flutter actual combat from scratch news client
https://space.bilibili.com/404904528/channel/detail?cid=106755
Flutter component development
https://space.bilibili.com/404904528/channel/detail?cid=144262
Flutter Bloc
https://space.bilibili.com/404904528/channel/detail?cid=177519
Flutter Getx4
https://space.bilibili.com/404904528/channel/detail?cid=177514
Docker Yapi
https://space.bilibili.com/404904528/channel/detail?cid=130578
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。