如何使用file_get_contents()向HTTP请求添加Authorization标头?

时间:2016-08-28 14:29:47

标签: php api http

正如标题所示,我无法为OAuth 1.0a受保护文件发出签名HTTP请求。 我正在尝试使用file_get_contents方法为请求添加Authorization标头,方法是使用stream_context_create()方法。 [下面的源代码]

$url = "https://rest.immobilienscout24.de/restapi/api/offer/v1.0/user/me/realestate";
    $context = stream_context_create(array(
        'http' => array(
            'header'  => "Authorization: OAuth
            oauth_consumer_key = \"MY_KEY\”,
            oauth_token = \"MY_TOKEN\"
            oauth_signature_method= \"HMAC-SHA1\",
            oauth_timestamp=\"TIMESTAMP\",
            oauth_nonce=\"MY_NONCE\",
            oauth_signature=\"MY_SIGNATURE\""
        )
    ));
    $data = file_get_contents($url, false, $context);

这是请求的样子

GET /api/file HTTP/1.1 Host: example.com
Authorization: OAuth oauth_consumer_key="KEY",
    oauth_token="TOKEN",
    oauth_signature_method="HMAC-SHA1",
    oauth_timestamp="TIMESTAMP",
    oauth_nonce="NONCE",
    oauth_signature="SIGNATURE"

问题:我总是得到以下错误: 无法打开流:HTTP请求失败! HTTP / 1.1 401在XX行未经授权。 我究竟做错了什么?它是否创建了标题? 我知道这可以用卷曲来完成,但我实际上没有使用卷曲的知识和经验。

感谢您的帮助!

1 个答案:

答案 0 :(得分:2)

根据OAuth 1.0a spec

  

OAuth协议参数通过以下方式在Authorization标头中发送:

     
      
  1. 参数名称和值按Parameter Encoding编码。

  2.   
  3. 对于每个参数,名称后面紧跟一个'='字符(ASCII码61),一个'''字符(ASCII码34),参数值(可能为空),另一个' “'字符(ASCII码34)。

  4.   
  5. 参数由逗号字符(ASCII代码44)和每 [RFC2617] 的可选线性空格分隔。

  6.   
  7. 根据 [RFC2617] 第1.2节添加和解释OPTIONAL领域参数。

  8.   

一个问题是您在标题字符串中插入\n LF )字符,根据RFC2617不允许这样做。你oauth_token之后似乎也错过了一个逗号。您是否正确编码参数也不清楚。

我认为避免犯这些错误的更简单方法可能是使用类似http_build_query的内容并将PHP_QUERY_RFC3986作为 enc_type 参数传递给{{3}这是OAuth 1.0a所声明的内容,或者您​​可以在单独的数组中设置参数,并RFC3986自行编码。

$params = [
    "realm"                  => $realm, /* optional */
    "oauth_consumer_key"     => $key,
    "oauth_token"            => $token,
    "oauth_signature_method" => $sigmeth,
    "oauth_timestamp"        => $timestamp,
    "oauth_nonce"            => $nonce,
    "oauth_signature"        => $sig,
];

选项1

/* This will give you the proper encoded string to include in your Authorization header */
$params = http_build_query($params, null, ',', PHP_QUERY_RFC3986);    

$opts = ["http" => ["header" => "Authorization: OAuth " . $params]];

$context = stream_context_create($opts);
$data = file_get_contents($url, false, $context);

选项2

$params = implode(',',array_map(function($v,$k) {
    return $k . '="' . rawurlencode($v) . '"';
}, $params, array_keys($params)));

$opts = ["http" => ["header" => "Authorization: OAuth " . $params]];

$context = stream_context_create($opts);
$data = file_get_contents($url, false, $context);

我认为选项2实际上更符合OAuth 1,因为http_build_query不会引用参数。 array_map将符合RFC3986,这有助于保持您的值正确编码。