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

Flutter Clean Architecture中如何全局访问授权令牌?

遵循Clean Architecture的令牌访问方案

不需要给每个数据源方法都手动传入令牌参数,以下是几种符合Clean Architecture原则的实现方式:

1. 基于抽象接口的令牌提供者(TokenProvider)

核心思路是通过依赖倒置原则,让需要令牌的模块依赖抽象接口,而非具体的令牌存储实现,同时由Auth模块负责令牌的更新和管理。

  • 定义抽象接口(放在Domain层,确保各层都可依赖):
abstract class TokenProvider {
  String? get currentToken;
}
  • 在Auth模块的Data层实现该接口,负责令牌的存储与更新:
class AuthTokenProvider implements TokenProvider {
  String? _token;

  @override
  String? get currentToken => _token;

  // 由Auth模块调用,比如登录成功后更新令牌,登出时置空
  void updateToken(String? newToken) {
    _token = newToken;
  }
}
  • 通过依赖注入工具(如get_it)注册抽象与实现的绑定:
getIt.registerSingleton<TokenProvider>(AuthTokenProvider());
  • 在数据源中注入TokenProvider并直接使用:
class AlimentRemoteDataSourceImpl implements AlimentRemoteDataSource {
  final HttpClient client;
  final TokenProvider tokenProvider;

  AlimentRemoteDataSourceImpl({
    required this.client,
    required this.tokenProvider,
  });

  @override
  Future<(List<AlimentModel>, int)> getAllAliments() async {
    final http.Response response = await client.get(
      Uri.http(APIBaseURL, '$routeName/all'),
      headers: generateHeaders(
        contentType: null,
        authorization: tokenProvider.currentToken,
      ),
    );
    // ... 原有逻辑不变
  }
}

这种方式的优势:

  • 符合Clean Architecture的依赖规则,依赖抽象而非具体实现
  • 测试时可轻松替换为Mock实现,便于单元测试
  • 令牌的管理完全由Auth模块负责,其他模块无需关心细节

2. 封装带令牌拦截的HTTP客户端

将令牌注入逻辑封装到HTTP客户端的拦截器中,让所有请求自动携带令牌,进一步简化数据源的代码。

  • 自定义HTTP客户端或使用拦截器(以Dio为例):
class AuthenticatedHttpClient {
  final Dio _dio;
  final TokenProvider _tokenProvider;

  AuthenticatedHttpClient(this._dio, this._tokenProvider) {
    _dio.interceptors.add(InterceptorsWrapper(
      onRequest: (options, handler) {
        final token = _tokenProvider.currentToken;
        if (token != null) {
          options.headers['Authorization'] = 'Bearer $token';
        }
        return handler.next(options);
      },
    ));
  }

  Future<Response> get(String path) => _dio.get(path);
  // 封装其他HTTP方法:post、put等
}
  • 数据源直接使用这个封装后的客户端,无需手动处理令牌:
class AlimentRemoteDataSourceImpl implements AlimentRemoteDataSource {
  final AuthenticatedHttpClient client;

  AlimentRemoteDataSourceImpl({required this.client});

  @override
  Future<(List<AlimentModel>, int)> getAllAliments() async {
    final Response response = await client.get('$routeName/all');
    // ... 原有逻辑不变
  }
}

为什么单例方式不够规范?

直接用SessionToken单例会导致:

  • 代码产生硬依赖,违反依赖倒置原则,难以替换或测试
  • 令牌的管理逻辑与使用逻辑耦合,不符合Clean Architecture的分层职责划分

内容的提问来源于stack exchange,提问作者Kilian Danckaerts

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 18:25:10