Flutter 如何将 Auth 令牌从 Flutter 安全存储设置为 dio header?

Flutter how can i set Auth token from flutter secure storage to dio header?

登录后,我将用户令牌设置为我的用户安全存储。喜欢:

Future<AuthResponseModel?> login(AuthRequstModel model) async {
    try {
      Response response = await _dio.post(loginPath, data: model);
      if (response.statusCode == 200) {
        final AuthResponseModel authResponseModel = AuthResponseModel.fromJson(response.data);
        if (authResponseModel.success!) {
          await UserSecureStorage.setField("token", authResponseModel.token);
          
        }
        return AuthResponseModel.fromJson(response.data);
      }

      return null;
    } catch (e) {
      return null;
    }
  }

用户安全存储 =>

class UserSecureStorage {
  static const _storage = FlutterSecureStorage();

  static Future setField(String key, value) async {
    await _storage.write(key: key, value: value);
  }
 static Future<String?> getField(key) async {
    return await _storage.read(key: key);
  }

但问题是,当我想制作 apiservice 时,当我想在 dio 的 header 中验证令牌时,我无法访问它,因为它是 future 函数。但我不能使用 await 因为它在 baseoption 内部。喜欢:

class ApiService {
  final _dio = Dio(BaseOptions(headers: {
    'authorization': 'Bearer ${UserSecureStorage.getField("token")}', //I cant access here its only giving instance.
  }));
  Future<Response?> get(String path) async {
    try {
      Response response = await _dio.get('${ApiConstants.BASE_URL}$path');
      if (response.statusCode == 200) {
        return response;
      }
      return null;
    } on DioError catch (e) {
      return null;
    }
  }

我能做些什么来解决这个问题?我在尝试获取令牌后尝试使用 .then(value=>value) 但也没有用。感谢回复!

你正在获取实例,因为 UserSecureStorage.getField("token") 是未来的,所以当你输入 await 关键字时你可以获得令牌

所以这样试试

等待UserSecureStorage.getField("令牌")

我认为令牌没有得到更新,因为 _dio 已经初始化。

尝试在发出 dio 请求时请求令牌,例如:

class ApiService {
  final _dio = Dio();
  Future<Response?> get(String path) async {
    try {
      Response response = await _dio.get('${ApiConstants.BASE_URL}$path', options: Options(headers: {"authorization": "Bearer ${UserSecureStorage.getField("token")}"}));
      if (response.statusCode == 200) {
        return response;
      }
      return null;
    } on DioError catch (e) {
      return null;
    }
  }

对所有请求在 get method to add headers for a single request or interceptors 中使用 options

我认为这不是一个容易解决的问题,我会尝试两种不同的方法,您可以在 Provider 等状态管理器中维护令牌,这样您就不必依赖异步函数来检索它,但这当然会在代码中添加状态管理器结构,这会使事情变得有点复杂。

解决这个问题的更简单的方法是在 ApiService 中包含一个异步初始化器 class 这样

class ApiService {

  late final _dio;

  Future<void> init() async {
  _dio = Dio(BaseOptions(headers: {
    'authorization': 'Bearer ${UserSecureStorage.getField("token")}', //I cant access here its only giving instance.
  }));}

  Future<Response?> get(String path) async {
    try {
      Response response = await _dio.get('${ApiConstants.BASE_URL}$path');
      if (response.statusCode == 200) {
        return response;
      }
      return null;
    } on DioError catch (e) {
      return null;
    }
  }

这给我们带来了一个新问题,我们必须在每次实例化 class ApiService 时调用 init,要解决这个问题,您可以使用包 get_it,它只允许实例化一旦 class 并从项目中的任何地方访问它。

希望本文能帮助您解决问题