You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Flutter的Retrofit中添加Bearer Token授权验证

在Flutter Retrofit中添加Bearer Token授权验证

步骤1:实现Token存储工具

先在pubspec.yaml中添加shared_preferences依赖,然后创建一个工具类用于Token的存取:

import 'package:shared_preferences/shared_preferences.dart';

class TokenManager {
  static Future<String?> getToken() async {
    final prefs = await SharedPreferences.getInstance();
    return prefs.getString('auth_token');
  }

  static Future<void> saveToken(String token) async {
    final prefs = await SharedPreferences.getInstance();
    await prefs.setString('auth_token', token);
  }

  static Future<void> clearToken() async {
    final prefs = await SharedPreferences.getInstance();
    await prefs.remove('auth_token');
  }
}

步骤2:给Dio添加请求拦截器

修改GetIt依赖注入中的Dio初始化逻辑,通过拦截器自动为需要授权的接口添加Bearer Token,同时排除登录、注册这类无需授权的接口:

var getIt = GetIt.I;
void locator() async {
  Dio dio = Dio();

  dio.interceptors.add(InterceptorsWrapper(
    onRequest: (options, handler) async {
      // 排除不需要授权的接口路径
      final noAuthPaths = ['auth/login', 'auth/singup'];
      if (!noAuthPaths.contains(options.path)) {
        final token = await TokenManager.getToken();
        if (token != null) {
          options.headers['Authorization'] = 'Bearer $token';
        }
      }
      return handler.next(options);
    },
    onError: (DioException error, handler) {
      // 处理Token过期的401状态码
      if (error.response?.statusCode == 401) {
        TokenManager.clearToken();
        // 这里可添加跳转到登录页的逻辑,比如使用Navigator
      }
      return handler.next(error);
    }
  ));

  getIt.registerLazySingleton(() => dio);

  ApiService apiService = ApiService(getIt.call());
  getIt.registerLazySingleton(() => apiService);

  Repository repository = Repository(getIt.call());
  getIt.registerLazySingleton(() => repository);

  LoginCubit loginCubit = LoginCubit(getIt.call());
  getIt.registerLazySingleton(() => loginCubit);
 
  GetProfileCubit getProfileCubit = GetProfileCubit(getIt.call());
  getIt.registerLazySingleton(() => getProfileCubit);
}

注意:locator函数改为异步后,需要在main函数中异步调用:

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await locator();
  runApp(MyApp());
}

步骤3:登录成功后保存Token

在登录逻辑中(比如LoginCubit),登录成功后将接口返回的Token存入本地:

// 假设你的AuthModel包含token字段
class LoginCubit extends Cubit<LoginState> {
  final Repository _repository;
  LoginCubit(this._repository) : super(LoginInitial());

  Future<void> login(Map<String, dynamic> credentials) async {
    emit(LoginLoading());
    try {
      final authModel = await _repository.logIn(credentials);
      // 保存获取到的Token
      await TokenManager.saveToken(authModel.token);
      emit(LoginSuccess(authModel));
    } catch (e) {
      emit(LoginFailure(e.toString()));
    }
  }
}

步骤4:验证授权逻辑

现在像getUser这类需要授权的接口,Dio会自动在请求头中携带Authorization: Bearer <你的Token>,无需修改ApiService中的接口定义。

额外说明

  • 若Token有过期时间,可在拦截器的onError中处理401状态码,清除Token并跳转登录页
  • 确保AuthModel类正确解析接口返回的token字段
  • 不想用shared_preferences的话,也可以通过Bloc状态、GetX存储等方式保存Token

内容的提问来源于stack exchange,提问作者Baby Satan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 06:40:26