Postman中正常的API令牌请求在PHP脚本中提示缺少grant_type参数
问题描述
我通过API获取令牌时,Postman调用能正常拿到结果,但使用Postman生成的PHP cURL代码却返回AADSTS900144错误,提示请求体必须包含grant_type参数。代码中已明确设置该参数,本地和服务器环境都测试过,也参考了相关帖子,问题仍未解决。
错误信息
{"error":"invalid_request","error_description":"AADSTS900144: The request body must contain the following parameter: 'grant_type'.\r\nTrace ID: 096b2d08-2a58-46b9-80a1-701867418c00\r\nCorrelation ID: c96623e2-475f-48c5-bced-a1e87a557705\r\nTimestamp: 2023-05-08 16:01:55Z","error_codes":[900144],"timestamp":"2023-05-08 16:01:55Z","trace_id":"096b2d08-2a58-46b9-80a1-701867418c00","correlation_id":"c96623e2-475f-48c5-bced-a1e87a557705","error_uri":"https://login.microsoftonline.com/error?code=900144"}
我的PHP代码
<?php $curl = curl_init(); curl_setopt_array($curl, array( CURLOPT_URL => 'https://api.myendpoint.com/api/oauth2/v2.0/token', CURLOPT_RETURNTRANSFER => true, CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 0, CURLOPT_FOLLOWLOCATION => true, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => 'POST', CURLOPT_POSTFIELDS => array( 'client_id' => '--hidden-for-obvious-reasons--', 'client_secret' => '--hidden-for-obvious-reasons--', 'grant_type' => 'client_credentials', 'scope' => 'https://api.myendpoint.com/.default' ), CURLOPT_HTTPHEADER => array( 'Content-Type: application/x-www-form-urlencoded', 'Ocp-Apim-Subscription-Key: hidden-for-obvious-reasons' ), )); $response = curl_exec($curl); if (curl_errno($curl)) { echo 'cURL Error: ' . curl_error($curl); exit; } curl_close($curl); echo "<pre>$response</pre>"; ?>
请问我可能遗漏了什么?为何请求体中的grant_type参数未被识别?
解决方案
问题出在请求体的格式处理上:当你给CURLOPT_POSTFIELDS传入数组时,PHP的cURL会自动将请求的Content-Type设置为multipart/form-data,但你手动指定了application/x-www-form-urlencoded,这就导致服务端无法正确解析你传入的参数,自然识别不到grant_type。
修复步骤
将CURLOPT_POSTFIELDS的数组转换为URL编码的字符串,使用http_build_query()函数处理即可:
<?php $curl = curl_init(); // 先定义参数数组 $postData = array( 'client_id' => '--hidden-for-obvious-reasons--', 'client_secret' => '--hidden-for-obvious-reasons--', 'grant_type' => 'client_credentials', 'scope' => 'https://api.myendpoint.com/.default' ); curl_setopt_array($curl, array( CURLOPT_URL => 'https://api.myendpoint.com/api/oauth2/v2.0/token', CURLOPT_RETURNTRANSFER => true, CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 0, CURLOPT_FOLLOWLOCATION => true, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => 'POST', // 用http_build_query将数组转为URL编码字符串 CURLOPT_POSTFIELDS => http_build_query($postData), CURLOPT_HTTPHEADER => array( 'Content-Type: application/x-www-form-urlencoded', 'Ocp-Apim-Subscription-Key: hidden-for-obvious-reasons' ), )); $response = curl_exec($curl); if (curl_errno($curl)) { echo 'cURL Error: ' . curl_error($curl); exit; } curl_close($curl); echo "<pre>$response</pre>"; ?>
额外检查点
- 确认你的PHP环境中cURL扩展正常启用
- 检查参数值是否包含特殊字符,若有需确保
http_build_query()能正确编码(该函数会自动处理) - 可以通过开启cURL的调试选项(
CURLOPT_VERBOSE)查看实际发送的请求头和体,确认格式是否正确
内容的提问来源于stack exchange,提问作者John Hubler
相关产品推荐
相关产品推荐

