PHP post 使用 cURL 和 cookie 请求

PHP post request with cURL and cookie

我正在尝试向需要登录的网页发出请求。 我成功地获取了带有 SESSID 的 cookie,并使用 curl:

将其写入文件
$username = 'xxx';
$password = 'xxxxxxx';
$url = 'http://example.com';
$cookie="cookie.txt";
$postdata = "username=$username&userpass=$password&autologin=1&userlogin=Login";

$ch = curl_init();
curl_setopt ($ch, CURLOPT_URL, $url);
curl_setopt ($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt ($ch, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.6) Gecko/20070725 Firefox/2.0.0.6");
curl_setopt ($ch, CURLOPT_TIMEOUT, 60);
curl_setopt ($ch, CURLOPT_FOLLOWLOCATION, 0);
curl_setopt ($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt ($ch, CURLOPT_COOKIEJAR, $cookie);
curl_setopt ($ch, CURLOPT_REFERER, $url);

curl_setopt ($ch, CURLOPT_POSTFIELDS, $postdata);
curl_setopt ($ch, CURLOPT_POST, 1);
$result = curl_exec ($ch);

curl_close($ch);

现在我想用 cookie 向站点发出 POST 请求,以便它识别我已登录。它使用 API returns JSON 信息,如果你确实要求: site.com/API/command.get(x) - 只是一个例子。所以如果你在浏览器中打开它,它 returns JSON 数据。

谁能帮我个办法,怎么办?我是 curl 新手。

无论我尝试什么,我都会被重定向到登录页面。 试图通过 curl_setopt ($ch, CURLOPT_COOKIEFILE, $cookie);,没有成功。

也许你会尝试 guzzle?我为一些游戏引擎写了代理,我也遇到了类似的 cookies 问题。

重要提示:我没有找到以键值样式操作 cookie 的简单方法。所以,对我来说,它的决定更接近于破解而不是解决方案。我把 cookie 粘到字符串上:

foreach ($request->cookies as $key => $cookie) {
    $cookie_str .= $key .'='.$cookie . ';
}

我的解决方案如下所示:

$client = new GuzzleHttp\Client([
    'headers' => [
        'Cookie' => $cookie_str
    ]
]);

$reqv = $client -> createRequest('POST', 'some_url');
$resp = $client -> send($reqv);

我发现 curl 的 cookie jar 有问题,所以我编写了自己的例程。还有其他时候我需要添加从页面抓取的cookies。
为此 CURLOPT_HEADER 必须为真。

 curl_setopt($ch, CURLOPT_HEADER, true);

  $data = curl_exec($ch);
  $skip = intval(curl_getinfo($ch, CURLINFO_HEADER_SIZE)); 
  $requestHeader= substr($data,0,$skip);
  $data =  substr($data,$skip);
  $e = 0;
  while(true){
    $s = strpos($requestHeader,'Set-Cookie: ',$e);
    if (!$s){break;}
    $s += 12;
    $e = strpos($requestHeader,';',$s);
    $cookie = substr($requestHeader,$s,$e-$s) ;
    $s = strpos($cookie,'=');
    $key = substr($cookie,0,$s);
    $value = substr($cookie,$s);
    $cookies[$key] = $value;
  }

然后使用$cookies[]:

 $cookie = '';
 $show = '';
 $delim = '';
 foreach ($cookies as $k => $v){
   $cookie .= "$delim$k$v";
   $delim = '; ';
 }

然后使用$cookie:

curl_setopt($ch, CURLOPT_COOKIE, $cookie );

遇到麻烦的时候,我经常把FOLLOWLOCATION设为false:

curl_setopt($ch, CURLOPT_FOLLOWLOCATION, false);

如果有重定向,您可以看到正在发生的事情,并且需要获取在重定向 URL 的响应 Header 中设置的 cookie,然后必须将 FOLLOWLOCATION 设置为 false .

当 curl URL 将您带到重定向 curl_getinfo 时,将获得重定向位置 URL。

$status = intval(curl_getinfo($ch,CURLINFO_HTTP_CODE));
if ($status > 299 && $status < 400){
  $url= curl_getinfo($ch,CURLINFO_REDIRECT_URL );
}
// update cookies, do not clear `cookies()`;

遇到困难时,我会使用这些选项来获得 Response 和 Response Headers。 curl_exec() 数据中的响应 Header 将是 return。请求 Header 将由 curl_getinfo()

return
curl_setopt($ch, CURLOPT_VERBOSE, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, $request);
curl_setopt($ch, CURLINFO_HEADER_OUT, true);
curl_setopt($ch, CURLOPT_HEADER, true);


$data = curl_exec($ch);
if (curl_errno($ch)){
    $data .= 'Retreive Base Page Error: ' . curl_error($ch);
}
else {
  $info = rawurldecode(var_export(curl_getinfo($ch),true));
  $data = curl_exec($ch);
  $skip = intval(curl_getinfo($ch, CURLINFO_HEADER_SIZE)); 
  $requestHeader= substr($data,0,$skip);
  $data =  substr($data,$skip);
  $filename = parse_url($url, PHP_URL_HOST);
  $filename .= parse_url($url, PHP_URL_PATH) . '.txt';
  $fp = fopen($filename,'w');
  fwrite($fp,$info\n$data");
  fclose($fp);

  $data =  substr($data,$skip);
}

header 和 HTML 都存储在文件中。然后您可以查看 HTTP Header、HTML 和 JavaScript。有时 cookie 是由 JavaScript document.cookie 设置的,或者用 window.location 重定向的页面,或者用 JS 单击 HTML 表单的提交按钮。在这些情况下,可能需要从 curl 数据中抓取 cookie 和/或重定向位置。


然后我使用 FireFox Inspector 或 Chrome 开发工具。

我转到“网络”选项卡

在 FireFox 中,我转到“设置”并打开 "Enable Persistent logs"
在 Chrome 中,我单击“网络”选项卡上的 "Preserve log"

然后我使用浏览器去任何我想去的地方。

现在我可以看到每个请求和响应,包括重定向,并将它们与保存 headers 进行比较。


当您需要 header 看起来与保存的浏览器 header 完全一样时:

创建一个数组来放置请求Header键值
使用您上传的请求 header 中的内容准确填写请求数组。
示例:

$request = array();
$request[] = "Host: www.example.com";
$request[] = "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8";
$request[] = "User-Agent: MOT-V9mm/00.62 UP.Browser/6.2.3.4.c.1.123 (GUI) MMP/2.0";
$request[] = "Accept-Language: en-US,en;q=0.5";
$request[] = "Connection: keep-alive";
$request[] = "Cache-Control: no-cache";
$request[] = "Pragma: no-cache";

添加到卷曲:

curl_setopt($ch, CURLOPT_HTTPHEADER, $request);

很多时候使用手机版要容易得多。很多时候桌面版页面需要 JavaScript 而移动版不需要。我将 FireFox 与用户代理切换器一起使用,使用旧的摩托罗拉用户代理来检索 headers 和 HTML。然后我在 curl 的 HTTPHEADER:

中使用相同的用户代理
request[] = 'User-Agent: MOT-V9mm/00.62 UP.Browser/6.2.3.4.c.1.123 (GUI) MMP/2.0

感谢大家的提示。 我是如何让它工作的是这段代码(我实际上使用了错误的 post 数据):

$username = 'xxx';
$password = 'xxxx';
$url = 'http://example.com'; //request to the page i want the content from
$cookie="cookie.txt";

$url1 = "http://example.com/command..";

//login form action url
$postinfo = "act=login&login=$username&pass=$password";

$cookie_file_path = "cookie.txt";

$ch = curl_init();
curl_setopt($ch, CURLOPT_HEADER, false);
curl_setopt($ch, CURLOPT_NOBODY, false);
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);

curl_setopt($ch, CURLOPT_COOKIEJAR, $cookie_file_path);
//set the cookie the site has for certain features, this is optional
curl_setopt($ch, CURLOPT_COOKIEFILE, $cookie_file_path);
curl_setopt($ch, CURLOPT_USERAGENT,
    "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7.12) Gecko/20050915 Firefox/1.0.7");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_REFERER, $_SERVER['REQUEST_URI']);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);

curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $postinfo);

$result = curl_exec($ch);
//var_dump($result);

//page with the content I want to grab
curl_setopt($ch, CURLOPT_URL, $url1);
//do stuff with the info with DomDocument() etc
$html = curl_exec($ch);
var_dump($html);
curl_close($ch);

我在这里的某个地方得到了这段代码 (Whosebug)。感谢post编辑它的人!不记得确切的名字。这很有魅力!