在PHP中生成OAuth 1签名

时间:2018-10-12 18:14:11

标签: php oauth

我正在尝试连接到LivePerson Engagement History API,但遇到了一个与生成的签名有关的问题。

首先,API已经提供了必需的使用者密钥,使用者密钥,访问令牌和令牌密钥。因此,我不必经历检索这些过程的过程。为了访问他们的API,我只需要provide the auth header。我已经使用Postman模拟了所有内容,并且一切正常。问题是当我尝试在班级中生成自己的时间戳记/即刻/签名时。

这是我的类中发送cURL请求的方法:

private function execute($options = array())
{
    if (!isset($options['url'])) {
        return;
    }

    $ch = curl_init($options['url']);

    $method = (isset($options['method'])) ? $options['method'] : 'GET';

    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);

    if (isset($options['auth']) && $options['auth']) {
        $timestamp = round(microtime(true) * 1000);
        $nonce = $this->getNonce(11);
        $version = "1.0";
        $signatureMethod = "HMAC-SHA1";
        $signature = $this->generateSignature($options, $timestamp, $nonce, $signatureMethod, $version);

        $authHeader = "Authorization: OAuth oauth_consumer_key=\"{$this->consumerKey}\",oauth_token=\"{$this->accessToken}\",oauth_signature_method=\"{$signatureMethod}\",oauth_timestamp=\"{$timestamp}\",oauth_nonce=\"{$nonce}\",oauth_version=\"{$version}\",oauth_signature=\"{$signature}\"";

        curl_setopt($ch, CURLOPT_HTTPHEADER, array(
            $authHeader,
            "Content-Type: application/json"
        ));
    }

    if (isset($options['body']) && !empty($options['body'])) {
        curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($options['body']));
    }

    $result = curl_exec($ch);
    curl_close($ch);

    return $result;
}

我直接从https://github.com/BaglerIT/OAuthSimple/blob/master/src/OAuthSimple.php复制了getNonce方法。

这是我编写的用于生成签名的方法(该签名已从各种SO帖子和其他来源整理而来):

protected function generateSignature($request, $timestamp, $nonce, $signatureMethod, $version)
{
    $base = $request['method'] . "&" . rawurlencode($request['url']) . "&"
        . rawurlencode("oauth_consumer_key=" . rawurlencode($this->consumerKey)
        . "&oauth_nonce=" . rawurlencode($nonce)
        . "&oauth_signature_method=" . rawurlencode($signatureMethod)
        . "&oauth_timestamp=" . $timestamp
        . "&oauth_version=" . $version);

    $key = rawurlencode($this->consumerSecret) . '&' . rawurlencode($this->tokenSecret);
    $signature = base64_encode(hash_hmac('sha1', $base, $key, true));

    return $signature;
}

实际上,我可以将授权标头从Postman复制并粘贴到我的$authHeader变量中,并替换除时间戳记/随机数/签名以外的所有内容,并且可以正常工作。

我现在从他们的服务器收到的响应是[code] => 0005,但是我在他们的文档中找不到任何有关响应代码的信息。

编辑:我错过了查看响应标头-确切的错误是无效签名。

3 个答案:

答案 0 :(得分:1)

为了使此功能生效,我做了两件事。在创建签名的基本字符串时,我缺少了oauth_token –根据OAuth Core 1.0 documentation,“参数是按名称使用字典顺序的字节顺序排序的。”

因此,我最终将参数重新排序为字母顺序。生成基本字符串的代码如下所示:

$base = $request['method'] . "&" . rawurlencode($request['url']) . "&"
        . rawurlencode("oauth_consumer_key=" . rawurlencode($this->consumerKey)
        . "&oauth_nonce=" . rawurlencode($nonce)
        . "&oauth_signature_method=" . rawurlencode($signatureMethod)
        . "&oauth_timestamp=" . rawurlencode($timestamp)
        . "&oauth_token=" . rawurlencode($this->accessToken)
        . "&oauth_version=" . rawurlencode($version));

我还对auth标头中的参数进行了重新排序,以匹配基本字符串的顺序:

$authHeader = "Authorization: OAuth oauth_consumer_key=\"{$this->consumerKey}\",oauth_nonce=\"{$nonce}\",oauth_signature_method=\"{$signatureMethod}\",oauth_timestamp=\"{$timestamp}\",oauth_token=\"{$this->accessToken}\",oauth_version=\"{$version}\",oauth_signature=\"{$signature}\"";

答案 1 :(得分:1)

$base = $request['method']
        . '&' . rawurlencode($request['url'])
        . '&' . rawurlencode('oauth_consumer_key=' . $this->consumerKey)
        . rawurlencode('&oauth_nonce=' . $nonce)
        . rawurlencode('&oauth_signature_method=' . $signatureMethod)
        . rawurlencode('&oauth_timestamp=' . $timestamp)
        . rawurlencode('&oauth_version=' . $version)
        . rawurlencode('&' . http_build_query($data));

$key = rawurlencode($this->consumerSecret) . '&';

$signature = rawurlencode(base64_encode(hash_hmac('SHA1', $base, $key, true)));

如果您要进行POST,请确保包括您发布的数据,否则签名将无效。

CURLOPT_HTTPHEADER => array(
    "authorization: OAuth oauth_consumer_key=\"{$consumerKey}\",oauth_signature_method=\"{$signatureMethod}\",oauth_timestamp=\"{$timestamp}\",oauth_nonce=\"{$nonce}\",oauth_version=\"{$version}\",oauth_signature=\"{$oauthSignature}\"",
    "content-type: application/x-www-form-urlencoded",
  ),

标题应该和上面一样

答案 2 :(得分:0)

这个固定版本对我有用:

function generateOauthSignature($method, $url, $consumerKey, $nonce, $signatureMethod, $timestamp, $version, $consumerSecret, $tokenSecret, $tokenValue, $extraParams = array())
    {
        $base = strtoupper($method) . "&" . rawurlencode($url) . "&"
            . rawurlencode("oauth_consumer_key=" . $consumerKey
            . "&oauth_nonce=" . $nonce
            . "&oauth_signature_method=" . $signatureMethod
            . "&oauth_timestamp=" . $timestamp
            . "&oauth_token=" . $tokenValue
            . "&oauth_version=" . $version);

            if (!empty($extraParams)) {
                $base .= rawurlencode("&" . http_build_query($extraParams));
            }

        $key = rawurlencode($consumerSecret) . '&' . rawurlencode($tokenSecret);
        $signature = base64_encode(hash_hmac('sha1', $base, $key, true));

        return rawurlencode($signature);
    }

以下 twitter 线程帮助了我:https://twittercommunity.com/t/how-to-generate-oauth-signature-when-post-json-body-in-php/87581