如何在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
相关产品推荐
相关产品推荐

