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

Flutter Dio POST请求始终返回419错误,Laravel后端返回200

问题描述

使用Flutter开发跨平台网页,对接Laravel后端时遭遇419错误:

  • Laravel后端日志显示登录请求返回200状态码,但Flutter端始终收到419错误,无法进入成功逻辑
  • 使用Dio ^5.1版本,Postman测试登录请求可正常完成,Flutter已配置IPv4地址作为BaseUrl,排除了127.0.0.1、10.0.0.2这类地址问题

相关代码

login_controller.dart

void submitLogin() async {
    try {
      bool isValid = await validateEmail(inputUser.text);
      if (isValid) {
        await api.call(
          {
            "email": inputUser.text,
            "password": inputPass.text,
          },
          endpoint: '/login',
          method: 'POST',
        );
      } else {
        showSnackbar(msg: "Algo errado, favor validar os dados inseridos.", type: 0);
      }
    } catch (e) {
      showSnackbar(msg: e.toString(), type: 0);
      Get.back();
    }
  }

api.call函数代码

Future<Response?> call(Map<String, dynamic> data, {required String endpoint, required String method}) async {
    try {
      if (token.value == "") {
        await getToken();
      }
      options.headers.addIf(token.value != "", 'token', token.value);
      if (method == "GET") {
        Response getResponse = await dio.get(endpoint);
        print(getResponse.statusCode);
        return getResponse;
      }
      if (method == "POST") {
        Response postResponse = await dio.post(endpoint, data: jsonEncode(data.values));
        print(postResponse.statusCode);
        return postResponse;
      }
    } on DioError catch (e) {
      print(e.response);
      showSnackbar(msg: e.toString(), type: 0);
    }
  }
解决方案

419错误在Laravel中本质是CSRF令牌验证失败,结合你的代码场景,问题出在以下几点:

1. POST请求参数格式错误

你在POST请求中使用jsonEncode(data.values),会将参数转为数组格式(如["xxx@xxx.com", "123456"]),但Laravel登录接口需要键值对结构的JSON(如{"email":"xxx@xxx.com","password":"123456"})。直接传入data即可,Dio会自动处理JSON编码:

Response postResponse = await dio.post(endpoint, data: data);

2. 缺少CSRF令牌及Cookie管理

Laravel默认要求POST请求携带CSRF令牌,Postman能成功是因为它自动保存了Laravel的Session Cookie,而Flutter端需要手动处理:

  • 先请求Laravel的/csrf-cookie接口,获取CSRF令牌(该接口会返回Set-Cookie头)
  • 将令牌放入请求头的X-CSRF-TOKEN字段(而非你当前用的token字段)
  • 给Dio配置Cookie管理器,确保能保存Session Cookie

修改后的api.call函数示例:

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

// 初始化Dio时配置Cookie管理器
final dio = Dio();
final cookieJar = CookieJar();
dio.interceptors.add(CookieManager(cookieJar));

Future<Response?> call(Map<String, dynamic> data, {required String endpoint, required String method}) async {
    try {
      // 非GET请求先获取CSRF令牌
      if (method != "GET") {
        await dio.get('/csrf-cookie');
      }
      // 从Cookie中提取CSRF令牌
      List<Cookie> cookies = await cookieJar.loadForRequest(Uri.parse("你的LaravelBaseUrl/csrf-cookie"));
      String? csrfToken = cookies.firstWhere((cookie) => cookie.name == 'XSRF-TOKEN', orElse: () => Cookie('', '')).value;
      if (csrfToken != "") {
        options.headers['X-CSRF-TOKEN'] = csrfToken;
      }
      
      if (method == "GET") {
        Response getResponse = await dio.get(endpoint);
        print(getResponse.statusCode);
        return getResponse;
      }
      if (method == "POST") {
        Response postResponse = await dio.post(endpoint, data: data);
        print(postResponse.statusCode);
        return postResponse;
      }
    } on DioError catch (e) {
      print(e.response);
      showSnackbar(msg: e.toString(), type: 0);
    }
  }

3. 检查Content-Type请求头

如果手动编码JSON,需确保请求头Content-Type设为application/json,不过直接传入Map给Dio时,它会自动设置该头,无需额外操作。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 22:10:31