Flutter中GraphQL动态添加Authorization Token问题求助
你的核心问题是GraphQL客户端初始化时Token还未获取,导致请求无法携带有效Token。以下是几种可行的解决方式:
方案一:使用AuthLink(推荐)
利用graphql_flutter提供的AuthLink,它会在每次请求发起前动态获取最新Token,完美适配Token后续获取的场景:
void main() async{ WidgetsFlutterBinding.ensureInitialized(); final _sessionDataProvider = SessionDataProvider(); // 初始化基础HttpLink,不预设Authorization头 final httpLink = HttpLink("https://my_api.ru/graphql/"); // 创建AuthLink,每次请求时自动拉取最新Token final authLink = AuthLink( getToken: () async { String? token = await _sessionDataProvider.getSessionId(); return token != null ? "Bearer $token" : null; }, ); // 拼接AuthLink和HttpLink,让请求先经过Token校验再发往服务器 final link = authLink.concat(httpLink); ValueNotifier<GraphQLClient> client = ValueNotifier(GraphQLClient( link: link, cache: GraphQLCache(store: InMemoryStore()), )); var app = GraphQLProvider(client: client, child: MyApp()); runApp(app); }
原理
AuthLink作为请求链路的前置环节,每次发起GraphQL请求时都会调用getToken方法获取最新的Token值,再将其注入请求头中。不管Token是初始化后多久获取到的,请求时都会带上当前最新的有效Token。
方案二:主动更新GraphQLClient
如果需要在Token更新(比如登录成功、刷新Token)后立刻让后续请求使用新Token,可以通过更新ValueNotifier中的GraphQLClient实现:
- 初始化时先创建不带Token的客户端:
void main() async{ WidgetsFlutterBinding.ensureInitialized(); final _sessionDataProvider = SessionDataProvider(); // 初始化无Token的HttpLink final httpLink = HttpLink("https://my_api.ru/graphql/"); ValueNotifier<GraphQLClient> client = ValueNotifier(GraphQLClient( link: httpLink, cache: GraphQLCache(store: InMemoryStore()), )); var app = GraphQLProvider(client: client, child: MyApp()); runApp(app); }
- 在获取到Token后(比如登录成功回调中)更新客户端:
// 假设登录成功后拿到了新token void updateClientWithNewToken(String newToken) { final newHttpLink = HttpLink( "https://my_api.ru/graphql/", defaultHeaders: {"Authorization": "Bearer $newToken"} ); // 更新ValueNotifier的值,所有依赖该客户端的组件会自动使用新配置 client.value = GraphQLClient( link: newHttpLink, cache: GraphQLCache(store: InMemoryStore()), ); }
方案三:自定义Auth头Link
如果需要更灵活的Token处理逻辑(比如添加Token过期判断),可以自定义一个Link来注入请求头:
class AuthHeaderLink extends Link { final SessionDataProvider sessionDataProvider; AuthHeaderLink(this.sessionDataProvider); @override Stream<Response> request(Request request, [NextLink? forward]) async* { String? token = await sessionDataProvider.getSessionId(); if (token != null) { // 将最新Token注入请求头 request = request.updateContextEntry<HttpLinkHeaders>( (headers) => HttpLinkHeaders( headers: { ...headers?.headers ?? {}, 'Authorization': 'Bearer $token', }, ), ); } // 传递请求到下一个链路环节 yield* forward!(request); } }
初始化时拼接使用:
void main() async{ WidgetsFlutterBinding.ensureInitialized(); final _sessionDataProvider = SessionDataProvider(); final httpLink = HttpLink("https://my_api.ru/graphql/"); final authHeaderLink = AuthHeaderLink(_sessionDataProvider); final link = authHeaderLink.concat(httpLink); ValueNotifier<GraphQLClient> client = ValueNotifier(GraphQLClient( link: link, cache: GraphQLCache(store: InMemoryStore()), )); var app = GraphQLProvider(client: client, child: MyApp()); runApp(app); }
内容的提问来源于stack exchange,提问作者Happy
相关产品推荐
相关产品推荐

