PHP:向 URL 添加参数时 OAuth 1.0 签名不正确

问题描述 投票:0回答:2

长话短说,这是我生成 OAuth 1.0 签名的函数,只要 URL 中没有添加任何参数,它就可以正常工作。即使添加单个参数也会导致我使用此函数连接的 API 发出“签名无效”响应。

function generateSignature($request, $timestamp, $nonce) {
  $parameters = array();
  ksort($request['params']);
  foreach($request['params'] as $key=>$value){
    $parameters[] = "$key=".rawurlencode($value);
  }

  $base = $request['method']."&".rawurlencode($request['url'])."&".rawurlencode(implode('&', $parameters))."&"
      .rawurlencode("oauth_consumer_key=".rawurlencode(consumer_key)
      ."&oauth_nonce=".rawurlencode($nonce)
      ."&oauth_signature_method=".rawurlencode("HMAC-SHA1")
      ."&oauth_timestamp=". rawurlencode($timestamp)
      ."&oauth_token=".rawurlencode(token)
      ."&oauth_version=".rawurlencode("1.0"));

    $key = rawurlencode(consumer_secret).'&'.rawurlencode(token_secret);
    $signature = base64_encode(hash_hmac('SHA1', $base, $key, true));
    return $signature;
}

该函数的使用如下。同样,当参数不存在时,这可以完美地工作:

$ch = curl_init();

$request = array();
$request['method'] = 'GET';
$request['url'] = base_url.'/orders';
$params = array();
$params['status'] = 'pending';
$request['params'] = $params;

$parameters = (empty($request['params'])) ? "" : "?".http_build_query($request['params']);

curl_setopt($ch, CURLOPT_URL, $request['url'].$parameters);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $request['method']);

$timestamp = time();
$nonce = generateNonce($timestamp);
$signature = generateSignature($request, $timestamp, $nonce);
$headers = array();
$headers[] = 'Authorization: OAuth realm="",oauth_version="1.0",oauth_consumer_key="'.consumer_key.'",oauth_token="'.token.'",oauth_timestamp="'.$timestamp.'",oauth_nonce="'.$nonce.'",oauth_signature_method="HMAC-SHA1",oauth_signature="'.$signature.'"';
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

我做错了什么?我检查了 OAuth 1.0 文档和 StackOverflow 的示例,但无法识别问题。

php curl oauth authorization signature
2个回答
0
投票

好的,找到问题了。包含参数的字符串应添加到基本字符串的末尾:

function generateSignature($request, $timestamp, $nonce) {
  $base = $request['method']."&".rawurlencode($request['url'])."&"
      .rawurlencode("oauth_consumer_key=".rawurlencode(consumer_key)
      ."&oauth_nonce=".rawurlencode($nonce)
      ."&oauth_signature_method=".rawurlencode("HMAC-SHA1")
      ."&oauth_timestamp=". rawurlencode($timestamp)
      ."&oauth_token=".rawurlencode(token)
      ."&oauth_version=".rawurlencode("1.0"));

      if (!empty($request['params'])) {
        $base .= rawurlencode("&".http_build_query($request['params']));
      }

    $key = rawurlencode(consumer_secret).'&'.rawurlencode(token_secret);
    $signature = base64_encode(hash_hmac('SHA1', $base, $key, true));
    return $signature;
}

0
投票

感谢您提供的这个示例,即使如此,我还是挣扎了几个小时才弄清楚,如果您的查询参数按字母顺序小于“oauth”,那么您需要将查询参数移至更靠近基数开头的位置。就我而言,查询参数是“id”。似乎基本字符串中的所有参数都需要按字母顺序排列,因此您可能在 oauth 参数之前和之后有一些查询参数。

$base = $request['method']."&".rawurlencode($request['url'])."&"
      .rawurlencode(http_build_query($request['params']))
      .rawurlencode("&oauth_consumer_key=".rawurlencode($consumer_key)
      ."&oauth_nonce=".rawurlencode($nonce)
      ."&oauth_signature_method=".rawurlencode("HMAC-SHA1")
      ."&oauth_timestamp=". rawurlencode($timestamp)
      ."&oauth_token=".rawurlencode($token)
      ."&oauth_version=".rawurlencode("1.0"));
© www.soinside.com 2019 - 2024. All rights reserved.