Flutter Dart使用Bearer Token请求API报401 同参数Swift请求正常
以下是该场景下按出现概率排序的常见诱因,对应修复方式可直接套用:
1. http库form编码默认值与头声明不匹配
这是该类问题最高发的坑:Dart官方http包对form请求的编码逻辑不会读取你手动在headers里写的charset配置——当你给post()传入Map<String,String>类型的body、且未显式指定encoding参数时,库会固定用ISO-8859-1(Latin-1)编码请求体,和你手动写的charset=UTF-8声明完全不一致。
只要请求体里存在任何非ASCII字符(中文、全角符号、Unicode特殊字符等),服务端收到的内容就是乱码,绝大多数API网关、WAF遇到这类头声明和实际编码不匹配的请求,会直接拦截返回401,根本不会走到后续的Bearer Token校验流程。
修复方法
显式给post方法传入utf8编码参数,强制库按UTF-8处理请求体:
var response = await client.post( url, headers: headers, body: body, encoding: utf8, );
如果改完仍有异常,可以直接把请求体手动编码成字节数组传入,彻底绕开库的默认编码逻辑:
import 'dart:convert'; // ... final encodedBody = utf8.encode(Uri(queryParameters: body).query); var response = await client.post( url, headers: headers, body: encodedBody, );
2. Client自动携带了历史无效Cookie
http.Client()默认会持久化同域名下所有历史请求的Cookie,并且在后续请求里自动携带。如果你在拿到有效Bearer Token之前,用同一个Client实例发过登录失败、未授权的请求,残留的过期Session、匿名标识Cookie会被自动带到本次请求中。
大量服务端的鉴权优先级是Cookie高于Authorization头,只要请求带了Cookie就优先校验Cookie合法性,Cookie无效直接返回401,完全不会校验你传入的Bearer Token。Swift端如果用的是临时会话、默认关闭Cookie持久化,就不会触发这个问题。
修复方法
要么每次发鉴权请求新建一个干净的Client实例,要么在headers里强制清空Cookie:
var headers = <String, String>{ // 原有Accept、Content-Type、Authorization配置保持不变 "Cookie": "", };
3. Token携带了肉眼不可见的冗余字符
即使你确认两端Token的文本内容完全一致,Dart端解析登录响应时,很容易把Token值前后的换行符、转义引号、空白字符一起截入变量——这类不可见字符无法通过肉眼排查,但拼入Authorization头后会直接导致Token校验失败。
修复方法
拼接头之前对Token做清洗:
// 去除前后空白、首尾可能被误解析进来的包裹引号 final validToken = rawToken.trim().replaceAll(RegExp(r'^"|"$'), ''); headers["Authorization"] = "Bearer $validToken";
4. 自动添加的隐式请求头触发服务端拦截
http库会自动给请求添加若干你没有手动配置的头,最常见的是Accept-Encoding: gzip、User-Agent: Dart/<版本号> (dart:io)。部分配置严格的企业级API会校验User-Agent白名单,遇到非预期的请求头会直接拦截返回401。
排查方法
本地起一个临时HTTP调试服务,把Dart端、Swift端发出的完整请求头、请求体逐字段对比,将Dart端自动添加的差异头手动覆盖为和Swift端完全一致的值即可。
内容的提问来源于stack exchange,提问作者Wrog

