我正在使用以下代码在我的dart应用程序中实现维基媒体的OAuth 2授权流:
String jsonString = jsonEncode(<String, String>{
'grant_type' : 'authorization_code',
'redirect_uri' : Uri.encodeFull(redirectUri),
'code' : authCode,
'client_id' : CLIENT_ID,
'client_secret' : clientSecret,
});
String paramName = 'param';
String formBody = paramName + '=' + Uri.encodeQueryComponent(jsonString);
List<int> bodyBytes = utf8.encode(formBody);
Future<http.Response> response = http.post(
Uri.parse('https://meta.wikimedia.org/w/rest.php/oauth2/access_token'),
headers: <String, String>{
"Content-Type": "application/x-www-form-urlencoded; charset=utf-8",
"Content-Length" : bodyBytes.length.toString()
},
body: bodyBytes,
);
这个的响应是:
{"error";invalid_request", "error_description"缺少必需的参数,包括无效的参数值;包含一个参数多次,或者格式不正确。",
提示": "检查' grant_type '参数", message"缺少必需的参数,包含无效的参数值,不止一次包含一个参数,或者是格式错误的。"}
,这可能与事实content - type仍然是JSON,即使我定义它的头application/x-www-form-urlencoded
或因为内容长度是1。
来自Flutter DevTools的头信息
Flutter DevTools的一般信息
为了匹配Content-Type
标头,您需要将参数编码为application/x-www-form-urlencoded
。
String body = Uri(queryParameters: <String, String> {
'grant_type' : 'authorization_code',
'redirect_uri' : Uri.encodeFull(redirectUri),
'code' : authCode,
'client_id' : CLIENT_ID,
'client_secret' : clientSecret,
}).query;
调用几乎相同:
Future<http.Response> response = http.post(
Uri.parse('https://meta.wikimedia.org/w/rest.php/oauth2/access_token'),
headers: <String, String>{
'Content-Type': 'application/x-www-form-urlencoded; charset=utf-8',
'Content-Length' : body.length.toString()
},
body: body,
);
附录
这样可以更简洁一些,将这两个部分合并到一个调用中:
Future<http.Response> response = http.post(
Uri.parse('https://meta.wikimedia.org/w/rest.php/oauth2/access_token'),
headers: <String, String>{
'Content-Type': 'application/x-www-form-urlencoded; charset=utf-8',
},
body: <String, String>{
'grant_type': 'authorization_code',
'redirect_uri': Uri.encodeFull(redirectUri),
'code': authCode,
'client_id': CLIENT_ID,
'client_secret': clientSecret,
}
);
注意,特定的Content-Length
报头是不必要的,因为这是在发送时计算的。