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

Flutter中Dio拦截器对接Laravel Sanctum的CSRF Token不匹配问题

解决Flutter Dio对接Laravel Sanctum时CSRF Token不匹配问题

1. 修正Laravel跨域配置(核心)

Laravel的config/cors.php必须正确配置,禁止用通配符*作为允许源,同时开启凭证支持:

return [
    'paths' => ['api/*', 'sanctum/csrf-cookie'],
    'allowed_methods' => ['*'],
    'allowed_origins' => ['http://localhost:8080', '你的Flutter应用实际域名'],
    'allowed_origins_patterns' => [],
    'allowed_headers' => ['*'],
    'exposed_headers' => [],
    'max_age' => 0,
    'supports_credentials' => true, // 必须设为true
];

同时更新.env文件的状态域配置:

SANCTUM_STATEFUL_DOMAINS=localhost,localhost:8080,你的实际域名

2. 让Dio自动管理Cookie

Dio默认不会自动保存和携带Cookie,需要引入dio_cookie_manager和cookie_jar包,配置CookieJar:

import 'package:dio/dio.dart';
import 'package:dio_cookie_manager/dio_cookie_manager.dart';
import 'package:cookie_jar/cookie_jar.dart';

// 初始化Dio并配置CookieJar
final dio = Dio();
final cookieJar = CookieJar();
dio.interceptors.add(CookieManager(cookieJar));
// 再添加你的CSRF拦截器
dio.interceptors.add(CsrfTokenInterceptor(dio, cookieJar));

关键原因:Sanctum验证CSRF时,需要同时校验请求头的X-XSRF-TOKEN和Cookie中的XSRF-TOKEN,只带请求头无法通过验证。

3. 简化拦截器逻辑

无需手动解析响应头的Cookie,直接从CookieJar中读取已保存的XSRF-TOKEN:

import 'dart:io';
import 'package:dio/dio.dart';
import 'package:cookie_jar/cookie_jar.dart';

class CsrfTokenInterceptor extends Interceptor {
  final Dio dio;
  final CookieJar cookieJar;

  CsrfTokenInterceptor(this.dio, this.cookieJar);

  @override
  Future<void> onRequest(RequestOptions options, RequestInterceptorHandler handler) async {
    List<String> methods = ['POST', 'PUT', 'DELETE', 'PATCH'];

    if (methods.contains(options.method)) {
      // 先获取CSRF Cookie并自动保存到CookieJar
      await dio.get('/sanctum/csrf-cookie');
      // 从CookieJar中取出XSRF-TOKEN
      final cookies = await cookieJar.loadForRequest(Uri.parse(dio.options.baseUrl));
      final xsrfToken = cookies.firstWhere((cookie) => cookie.name == 'XSRF-TOKEN', orElse: () => null);
      if (xsrfToken != null) {
        options.headers['X-XSRF-TOKEN'] = Uri.decodeFull(xsrfToken.value);
      }
    }

    handler.next(options);
  }
}

4. 验证请求的Cookie是否正确携带

在拦截器中打印请求的Cookie头,确认包含XSRF-TOKEN和laravel_session:

@override
void onRequest(RequestOptions options, RequestInterceptorHandler handler) {
  print('Request Cookie: ${options.headers[HttpHeaders.cookieHeader]}');
  // 其他逻辑...
}

如果Cookie头为空,说明Dio的CookieJar未正确配置。

5. 对齐Postman与Flutter的请求参数

对比两者的请求信息,确保:

  • 请求的域名/端口完全一致(避免映射域名和本地地址混用)
  • X-XSRF-TOKEN的值解码后与Postman一致
  • 请求头中携带了完整的Cookie字段

内容的提问来源于stack exchange,提问作者raw.nato

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 11:06:16