使用Flutter dart:io发送Token Post请求报错unsupported_grant_type
解决dart:io HttpClient请求ASP.NET Web API Token返回
unsupported_grant_type的问题 我来帮你搞定这个问题!你遇到的unsupported_grant_type错误,核心原因是请求体的编码方式不符合API要求——你用dart:io实现时错误地把参数转换成了JSON格式,但ASP.NET的Token端点需要的是application/x-www-form-urlencoded类型的表单数据,这和你用http包、Postman成功的请求格式一致。
问题出在哪?
当你用http包的post方法传入body为Map时,它会自动帮你把这个Map编码成x-www-form-urlencoded格式的字符串(比如username=MyUsername&password=MyPassword&grant_type=password),同时自动设置正确的Content-Type。但你用dart:io的HttpClient时,却用了json.encode(payLoad)把参数转成了JSON字符串,服务器收到后无法解析出grant_type参数,所以返回了错误。
修正后的代码
把请求体的编码方式改成x-www-form-urlencoded格式即可,这里可以用Uri类的工具方法来自动生成正确编码的表单字符串:
import 'dart:io'; import 'dart:convert'; Future<String> getToken() async { Uri address = Uri.parse('https://myaddress:myport/token'); HttpClient httpClient = HttpClient(); httpClient.connectionTimeout = Duration(seconds: 20); httpClient.badCertificateCallback = ((X509Certificate cert, String host, int port) => true); // 允许自签名证书 HttpClientRequest request = await httpClient.postUrl(address); final Map<String, String> payLoad = { 'username': 'MyUsername', 'password': 'MyPassword', 'grant_type': 'password' }; // 关键:把Map转换成x-www-form-urlencoded格式的字符串 String formData = Uri(queryParameters: payLoad).query; request.headers.contentType = ContentType("application", "x-www-form-urlencoded", charset: "utf-8"); request.add(utf8.encode(formData)); // 用utf8编码表单字符串 HttpClientResponse response = await request.close(); String responseBody = await response.transform(utf8.decoder).join(); httpClient.close(); return responseBody; }
核心要点总结
- 不要对Token请求的参数使用JSON编码,ASP.NET的Token端点只接受
application/x-www-form-urlencoded格式的表单数据 - 用
Uri(queryParameters: payLoad).query可以安全地将Map转换为符合要求的编码字符串,自动处理特殊字符的转义 - 保持
badCertificateCallback的设置不变,确保能正常连接自签名证书的服务器
内容的提问来源于stack exchange,提问作者Elmer
相关产品推荐
相关产品推荐

