【问题标题】:How to add an Authorization header to a HTTP request with file_get_contents()?如何使用 file_get_contents() 向 HTTP 请求添加授权标头?
【发布时间】:2017-01-04 15:54:05
【问题描述】:

正如标题所说,我在为受 OAuth 1.0a 保护的文件发出签名 HTTP 请求时遇到问题。 我正在尝试对请求使用 file_get_contents 方法,并希望通过使用 stream_context_create() 方法添加 Authorization 标头。 【源码如下】

$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 行未授权。 我究竟做错了什么?它是在创建标题吗? 我知道这也可以用 curl 来完成,但我对使用 curl 几乎一无所知。

感谢您的帮助!

【问题讨论】:

    标签: php api http


    【解决方案1】:

    根据OAuth 1.0a spec

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

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

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

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

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

    一个问题是您将\n (LF) 字符插入到标题字符串中,根据 RFC2617,这是不允许的。在oauth_token 之后,您似乎还缺少一个逗号。您是否正确编码参数也不清楚。

    我认为避免犯这些错误的更简单方法是使用 http_build_query 之类的东西并将 PHP_QUERY_RFC3986 作为 enc_type 参数传递以符合 RFC3986,这就是OAuth 1.0a 声明它遵循,或者您可以将参数设置在一个单独的数组中,然后array_map 自己对其进行编码。

    $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 不会引用参数。 rawurlencode 将符合 RFC3986,这将有助于正确编码您的值。

    【讨论】:

    • 谢谢!我必须在授权标头中提供它们。仍然得到同样的错误。是否有可能看到我的 xampp-server 发送的请求?也许我可以找到错误然后......
    • 抱歉,我之前从未真正阅读过 OAuth 1.0 规范。我认为没有人仍在使用 OAuth1,但经过快速审查后,我修改了我的答案以更恰当地解决您的问题。它特定于 OAuth1。我只是回答,好像这是一个一般的 HTTP 问题。
    • 再次感谢!我测试了这两个选项。仍然是同样的错误。如果我的密钥和签名有误,我会得到同样的错误吗?
    • 我怀疑是这样。 According to the spec:“当服务提供者拒绝消费者请求时,它应该以 HTTP 400 Bad Request 或 HTTP 401 Unauthorized 响应。”。它列出了 无效签名无效消费者密钥 作为 401 响应代码等的一些原因。但是不支持的签名方法被列为400。所以这可能会为你缩小一点。
    猜你喜欢
    • 2020-10-11
    • 2020-03-29
    • 2018-05-04
    • 2018-11-25
    • 2019-01-10
    • 1970-01-01
    • 2014-12-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多