使用PHP生成OAuth 1.0签名失败,API返回401无效签名求助
解决OAuth 1.0调用返回401无效签名的问题
问题根源分析
你的代码存在两个核心问题,直接导致了无效签名的401错误:
- Authorization头语法错误:
oauth_signature字段的引号闭合逻辑错误,原代码中多写了一个闭合引号,导致API无法正确解析签名内容。 - Nonce生成不符合规范:OAuth 1.0要求
nonce是每个请求唯一的随机字符串,同一时间戳下不能重复。你当前的实现基于截短的时间戳生成,同一分钟内所有请求的nonce完全相同,违反了唯一性要求。
修正后的代码
const consumer_key = "20CECD28B41A458E9E328BB45C26EACB"; const consumer_secret = "F485B390C5854A69A8DA17554E689D03"; const token = "5F3C117598A14BE8B7136659AB2251C0"; const token_secret = "647E14C4F7EF4DA5AA119D5C60E95114"; // 生成符合OAuth规范的唯一随机nonce function generateNonce() { return bin2hex(random_bytes(16)); } function generateSignature($request, $timestamp, $nonce){ // 按字典序排列OAuth参数(必须严格排序) $params = [ 'oauth_consumer_key' => consumer_key, 'oauth_nonce' => $nonce, 'oauth_signature_method' => "HMAC-SHA1", 'oauth_timestamp' => $timestamp, 'oauth_token' => token, 'oauth_version' => "1.0" ]; // 构建编码后的参数字符串 $paramString = ''; foreach ($params as $key => $value) { $paramString .= rawurlencode($key) . '=' . rawurlencode($value) . '&'; } $paramString = rtrim($paramString, '&'); // 构建签名基字符串 $base = $request['method'] . "&" . rawurlencode($request['url']) . "&" . rawurlencode($paramString); $key = rawurlencode(consumer_secret) . '&' . rawurlencode(token_secret); $signature = base64_encode(hash_hmac('SHA1', $base, $key, true)); return $signature; } $ch = curl_init(); $request = [ 'url' => 'https://someniceapi.com', 'method' => 'GET' ]; curl_setopt($ch, CURLOPT_URL, $request['url']); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $request['method']); $timestamp = time(); $nonce = generateNonce(); $signature = generateSignature($request, $timestamp, $nonce); // 修正Authorization头的引号错误 $headers = [ 'Authorization: OAuth oauth_consumer_key="'.consumer_key.'",oauth_token="'.token.'",oauth_signature_method="HMAC-SHA1",oauth_signature="'.$signature.'",oauth_timestamp="'.$timestamp.'",oauth_nonce="'.$nonce.'",oauth_version="1.0"' ]; curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); $result = curl_exec($ch); // 可选:添加curl错误排查 if(curl_errno($ch)){ echo 'Curl错误: ' . curl_error($ch); } curl_close($ch);
关键修正说明
- Nonce生成:改用
random_bytes(16)生成随机字节并转十六进制,确保每个请求的nonce唯一,完全符合OAuth 1.0规范。 - Authorization头修复:修正了
oauth_signature字段的引号闭合逻辑,保证参数格式被API正确解析。 - 参数字符串构建:改用循环拼接参数,更清晰地遵循“键值对分别编码后用&连接”的规则,避免手动拼接的疏漏。
额外验证提示:确保本地服务器时间与API服务器时间偏差在5分钟内,OAuth通常允许这个时间误差,超出范围会导致timestamp无效。
内容的提问来源于stack exchange,提问作者PaulJK
相关产品推荐
相关产品推荐

