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

Flutter&Dio空安全改造后API客户端遇400 Bad Request问题求助

排查Flutter调用dj-rest-auth登录接口400错误的方案

400 Bad Request本质是后端判定请求不符合要求,结合你是适配空安全代码后出现的问题,从以下方向逐一排查:

1. 先获取后端返回的具体错误细节

Django日志仅显示400,但响应体的42字节内容必然包含具体错误(比如参数为空、格式不匹配)。在login请求的回调里添加打印:

.then((response) {
  print('登录响应详情: ${response.data}'); // 关键:看后端给出的具体错误提示
  // 原有逻辑代码...
})
.catchError((err) {
  print('请求异常信息: $err');
});

常见错误如{"non_field_errors": ["无法使用提供的凭据登录"]}或{"email": ["此字段为必填项"]},能直接定位问题根源。

2. 确保请求参数非空且格式合规

当前login方法的password和email参数无类型约束,空安全改造后很可能传入null值,导致请求体字段为空触发后端验证失败。修改方式:

  • 给参数添加非空类型与必填约束:
void login({required String password, required String email, required Function(LoginResponse) callback}) {
  print('传入参数校验: email=$email, password=$password'); // 先确认参数不为空
  // 原有请求逻辑...
}

调用时必须传入非空字符串,避免null被传递到后端。

3. 对齐请求头与数据格式和dj-rest-auth要求

dj-rest-auth默认接收application/json格式请求,虽Dio默认已设置,但可显式指定确保无偏差:

_dio.post(
  API_HOST + "dj-rest-auth/login/",
  data: {
    'email': email,
    'password': password,
  },
  options: Options(
    validateStatus: (status) => status! < 500,
    contentType: Headers.jsonContentType, // 显式声明JSON格式
  ),
)

同时对比Postman的请求:检查Postman的Content-Type、请求体格式,若Postman用form-data,Flutter需对应改为data: FormData.fromMap(...)。

4. 添加Dio日志拦截器,监控实际请求细节

通过日志拦截器查看完整请求信息(请求头、请求体、响应),和Postman请求做对比:

// 初始化Dio时添加拦截器
_dio.interceptors.add(LogInterceptor(
  requestBody: true,
  responseBody: true,
  requestHeader: true,
));

控制台会打印所有请求细节,能快速找出和Postman请求的差异点。

5. 简化代码排查空安全逻辑干扰

先写极简测试请求,确认参数和格式无问题:

void testLogin() {
  _dio.post(
    API_HOST + "dj-rest-auth/login/",
    data: {
      'email': '你的测试邮箱',
      'password': '你的测试密码',
    },
  ).then((res) {
    print('测试响应: ${res.statusCode}, ${res.data}');
  }).catchError((err) {
    print('测试错误: $err');
  });
}

若测试成功,说明问题出在原有空安全逻辑(如AuthTokens.fromJson解析错误、callback参数处理);若仍返回400,则是请求本身的参数/格式问题。

修复后的login代码示例

void login({required String password, required String email, required Function(LoginResponse) callback}) {
  print('登录参数校验: email=$email, password=$password');
  _dio.post(
    API_HOST + "dj-rest-auth/login/",
    data: {
      'email': email,
      'password': password,
    },
    options: Options(
      validateStatus: (status) => status! < 500,
      contentType: Headers.jsonContentType,
    ),
  ).then((response) {
    print('登录响应: ${response.statusCode}, ${response.data}');
    AuthTokens? authTokens;
    if (response.statusCode == 200) {
      try {
        authTokens = AuthTokens.fromJson(response.data);
      } catch (e) {
        print('解析AuthTokens失败: $e');
      }
    }
    if (authTokens != null) {
      authTokens.save();
      callback(LoginResponse(response.statusCode, authTokens));
    } else {
      print('登录失败或令牌解析失败');
      // 可补充:给callback传递失败状态,比如LoginResponse(response.statusCode, null)
    }
  }).catchError((error) {
    print('请求出错: $error');
  });
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 03:40:29