【问题标题】:Get set-cookie header from redirect php从重定向 php 获取 set-cookie 标头
【发布时间】:2016-03-05 16:12:36
【问题描述】:

好的,我还没有找到解决这个问题的方法,我需要开始就 SO 提出问题,这样我才能提高我的声誉并希望能帮助到其他人。

我正在制作一个 wordpress 插件,用于从远程站点检索项目的 json 列表。最近,该网站为 cookie 添加了重定向检查。

在没有 cookie 的第一次请求时,提供 302 标头,指向第二个页面,该页面也返回指向主页的 302 重定向。但是,在第二页上,还提供了 set-cookie 标头,这可以防止主页再次重定向。

但是,当我向网站上的 url 发出 cURL 请求时,它会在重定向循环中失败。

现在,显然最简单的解决方案是在远程服务器上解决此问题。它不应该为 api 路由实现该重定向。但目前这对我来说不是一个选择。

我找到了如何从 2** 代码响应中检索 set-cookie 标头值,但是当提供 302 标头时,我似乎无法弄清楚如何访问该值,并且 cURL 只返回一个错误。

有没有办法在达到最大 (20) 重定向时访问标头?

是否可以在一定数量的重定向后停止执行?

如何获取此 cookie 的值,以便在最终请求中提供它?

【问题讨论】:

    标签: php curl cookies


    【解决方案1】:

    在您开始尝试将 cookie 添加到组合中之前,您已经遇到了问题。执行单个重定向对性能不利。使用 302 响应作为在 HTTP/1,1 或更高版本下将数据表示与数据检索分离的一种方式是不好的(它有效,但违反了协议 - 如果您确实必须重定向,则应该使用 303 )。

    尝试在 3xx 响应中设置 cookie 将无法在浏览器中始终如一地工作。在 Ajax 响应中设置 cookie 将无法在不同浏览器中始终如一地工作。

    它不应该为 api 路由实现重定向

    也许远程站点的人正试图阻止您窃取他们的内容?

    首先在 iframe 中获取主页以填充 cookie 并在浏览器的域中记录一个标志。

    【讨论】:

    • 不,我有完全的访问权限,这是一个工作项目。他们实现了重定向并破坏了他们请求的插件。这是一个客户,所以我不会抹黑。他们很可能会删除重定向(最终)。我只是想为自己的学习目的克服它,并继续研究它的其他方面。但我会传递信息,我不知道关于 3xx 的回复,还有其他需要调查的内容。
    • 我不确定我是否同意这里所说的几乎所有内容。 301 和 302 重定向有其用途并且被广泛使用。根据我的经验,所有浏览器都可以很好地处理 30 倍响应以及 Ajax 响应中设置的 cookie。
    【解决方案2】:

    我实际上发现了另一个 SO 问题,当然是在我发布之后,它引导我朝着正确的方向发展,HERE

    我使用WebGet 类发出 curl 请求。它已经三年没有维护了,但它仍然可以正常工作。

    它有一个功能,可以在不执行重定向循环的情况下发出 curl 请求。

    该函数中设置了很多 curl 选项,并且 curl 不会在其中返回错误,因此我确信确切的解决方案可能会更简单。 HERE 是一个 curl 选项列表,供任何想要深入研究的人使用。

    这是我如何处理每个响应以获得最终响应

            $w = new WebGet();
    
            $cookie_file = 'cookie.txt';
    
            if (!file_exists($cookie_file)) {
                $cookie_file_inter = fopen($cookie_file, "w");
                fclose($cookie_file_inter);
            }
    
            $w->cookieFile = $cookie_file; // must exist and be writable
            $w->requestContent($url);
    
            $headers = $w->responseHeaders;
    
            if ($w->responseStatusCode == 302 && isset($headers['LOCATION'])) {
                $w->requestContent($headers['LOCATION']);
            }
    
            if ($w->responseStatusCode == 302 && isset($headers['LOCATION'])) {
                $w->requestContent($headers['LOCATION']);
            }
    
            $response = $w->cachedContent;
    

    当然,这都是非常糟糕的做法,并且会对性能产生严重影响,但可能会有一些罕见的用例发现自己需要这样做。

    【讨论】:

      【解决方案3】:

      如果您使用 cURL 选项 CURLOPT_HEADER,您从 curl_exec 返回的数据将包括每个响应的标头,包括 302。

      如果您在 cURL 中启用 cookie 处理,它应该可以很好地获取 302 响应设置的 cookie,除非您更喜欢手动处理它。

      当可能有多个重定向时,我经常这样做:

      $ch = curl_init($some_url_that_302_redirects);
      curl_setopt($ch, CURLOPT_HEADER, 1);
      curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
      curl_setopt($ch, CURLOPT_COOKIEFILE, ''); // enable curl cookie handling
      
      $result = curl_exec($ch);
      // $result contains the headers from each response, plus the body of the last response
      
      $info   = curl_getinfo($ch); // info will tell us how many redirects were followed
      
      for ($i = 0; $i < intval($info['redirect_count']); ++$i) {
          // get headers from each response
          list($headers, $response) = explode("\r\n\r\n", $response, 2);
      
          // DO SOMETHING WITH $headers HERE
          // If there was a redirect, headers will be all headers from that response,
          // including Set-Cookie headers
      }
      
      list($headers, $body) = explode("\r\n\r\n", $response, 2);
      
      // Now $headers are the headers from the final response
      // $body is the content from the final response
      

      【讨论】:

      • 是的,做到了。我可以通过这种方式检索我正在寻找的 cookie。我在回答中提到的包有点简单,但实际上并没有回答这个问题。我会将您的答案标记为答案。
      • @D.Meganoski 很高兴该代码很有帮助,如果您有任何其他问题,请告诉我。我有一个非常标准的“parseHeaders”函数,如果你有兴趣,我会用到它。
      猜你喜欢
      • 1970-01-01
      • 2020-02-14
      • 1970-01-01
      • 1970-01-01
      • 2013-02-12
      • 2021-10-21
      • 2021-03-20
      • 1970-01-01
      • 2019-05-18
      相关资源
      最近更新 更多