如何用PHP cURL生成Twitter API 1.1签名?认证错误排查
原生PHP实现Twitter(X) API OAuth签名认证失败排查(错误码32)
我尝试仅使用PHP和cURL为Twitter(X)API生成签名,不借助任何库或包,完全原生实现。已仔细阅读API文档并按步骤操作,但仍遇到认证错误,错误信息如下:
{"errors":[{"code":32,"message":"Could not authenticate you."}]}
我的主代码:
<?php date_default_timezone_set('UTC'); $keys = array( "consumer_key" => "", // 替换为你的consumer key "consumer_secret" => "", // 替换为你的consumer secret "bearer_token" => "", "token_identifier" => "", // 替换为你的access token "token_secret" => "" // 替换为你的access token secret ); $method = "POST"; $status = "Hello World!"; $endpoint = "https://api.twitter.com/1.1/statuses/update.json"; $nounce = bin2hex(random_bytes(16)); $T = time(); // 补全时间戳变量 $params = [ "status" => $status, "include_entities" => "true", "oauth_consumer_key" => $keys['consumer_key'], "oauth_nonce" => $nounce, "oauth_signature_method" => "HMAC-SHA1", "oauth_timestamp" => $T, "oauth_token" => $keys['token_identifier'], "oauth_version" => "1.0", ]; // 直接调用全局签名函数,而非$API->signature $signature = signature($method, $endpoint, $params, $keys['consumer_secret'], $keys['token_secret']); echo $signature . '<br><br>'; $authHeader = 'OAuth '; $authParams = array( "oauth_consumer_key" => $keys['consumer_key'], "oauth_nonce" => $nounce, "oauth_signature" => $signature, "oauth_signature_method" => "HMAC-SHA1", "oauth_timestamp" => $T, "oauth_token" => $keys['token_identifier'], "oauth_version" => "1.0", ); $headerParts = []; foreach ($authParams as $key => $value) { if (strpos($key, 'oauth_') === 0) { // 替换HTML转义引号为直接双引号 $headerParts[] = $key . '="' . rawurlencode($value) . '"'; } } $authHeader .= implode(', ', $headerParts); echo $authHeader . '<br><br>'; $curl = curl_init(); curl_setopt_array($curl, [ CURLOPT_URL => $endpoint, CURLOPT_RETURNTRANSFER => true, CURLOPT_POST => true, CURLOPT_POSTFIELDS => http_build_query(['status' => $status]), CURLOPT_HTTPHEADER => [ 'Authorization: ' . $authHeader, 'Content-Type: application/x-www-form-urlencoded', ], ]); $response = curl_exec($curl); echo curl_errno($curl) ? 'Curl error: ' . curl_error($curl) : 'Response: ' . $response . '<br><br>'; curl_close($curl); ?>
我的签名函数:
function signature($method, $endpoint, $params, $consumerSecret, $tokenSecret = ''){ $encodedParams = []; // 对参数的键和值都进行RFC3986编码 foreach($params as $key => $value){ $encodedParams[rawurlencode($key)] = rawurlencode($value); } ksort($encodedParams); $paramString = http_build_query($encodedParams, '', '&', PHP_QUERY_RFC3986); $encodedUrl = rawurlencode($endpoint); $encodedParamString = rawurlencode($paramString); $signatureBaseString = strtoupper($method) . "&" . $encodedUrl . "&" . $encodedParamString; $encodedConsumerSecret = rawurlencode($consumerSecret); $encodedTokenSecret = rawurlencode($tokenSecret); $signingKey = $encodedConsumerSecret . "&" . $encodedTokenSecret; $hash = hash_hmac('sha1', $signatureBaseString, $signingKey, true); $signature = base64_encode($hash); return $signature; }
错误原因及修正说明
- 未定义时间戳变量:原代码中
$T未赋值,OAuth要求oauth_timestamp必须是当前UTC时间的Unix秒数,需添加$T = time();。 - 参数编码不完整:签名函数未对参数的键和值做RFC3986编码,OAuth规范要求所有参与签名的参数都要先编码再排序拼接,修正了
$encodedParams的赋值逻辑。 - OAuth头部格式错误:原代码使用HTML转义的
",应直接使用双引号,确保头部符合OAuth格式要求。 - 无效的curl重复调用:
curl_close()后再操作curl资源会触发错误,移除了这部分冗余代码。 - 函数调用方式错误:原代码使用
$API->signature(),但签名函数是全局函数,需直接调用signature()。
内容的提问来源于stack exchange,提问作者FarrisFahad
相关产品推荐
相关产品推荐

