cURL不发送POST数据

时间:2016-02-07 06:26:26

标签: php curl

也许我只需要一双新鲜的眼睛......

我需要POST到.htaccess基本身份验证后面的页面。我成功登录并通过.htBA,然后POST到目标页面。我知道脚本正在访问该页面,因为我正在记录访问权限。但是$ _POST是空的 - 从检查var以及目标脚本不能正常工作中可以看出这一点。 (我控制所有页面。)

我尝试了以下各种卷曲选项的许多组合无济于事。我没有从第二次点击中得到任何错误。

感谢。

$post_array = array(
  'username'=>$u,
  'password'=>$p
);


// Login here
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'http://example.com/admin/login.php');
curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.11; rv:43.0) Gecko/20100101 Firefox/43.0');
curl_setopt($ch, CURLOPT_COOKIEJAR, realpath('temp/cookies.txt') );
curl_setopt($ch, CURLOPT_COOKIEFILE, realpath('temp/cookies.txt'));
curl_setopt($ch, CURLOPT_COOKIESESSION, true);
curl_setopt($ch, CURLOPT_HEADER, true);
curl_setopt($ch, CURLOPT_MAXREDIRS, 10);
curl_setopt($ch, CURLOPT_REFERER, 'http://example.com/index.php');
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($post_array));
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
  'method' => 'POST',
  "Authorization: Basic ".base64_encode("$username:$password"),
));
$logInFirst = curl_exec ($ch);


/* Don't close handle as need the auth for next page
 * load up a new page */
$post_array_2 = array(
    'localfile'=>'my_data.csv',
    'theater_mode'=>'normal'
    );
//curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_COOKIEJAR, realpath('temp/cookies.txt') );
curl_setopt($ch, CURLOPT_COOKIEFILE, realpath('temp/cookies.txt'));
curl_setopt($ch, CURLOPT_COOKIESESSION, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_REFERER, 'http://example.com/admin/post_here.php');
curl_setopt($ch, CURLOPT_URL, 'http://example.com/admin/post_here.php');
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($post_array_2));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
//curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
  'Content-Type: multipart/form-data;',
  "Authorization: Basic ".base64_encode("$username:$password"),
));
$runAi = curl_exec($ch);
$run_error = curl_error($ch); echo '<hr>'.$run_error.'<hr>';
curl_close($ch);

这是目标页面上的代码(post_here.php),这导致零计数。所以我知道目标脚本正在被命中,并且根据输出,没有POST。

$pa = '   There are this many keys in POST: '.count($_POST);
foreach ($_POST as $key => $value) {
  $pa .= '   '.$key.':'.$value.'    ----  ';
}

2 个答案:

答案 0 :(得分:1)

错误发生在第二个请求中:

curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($post_array_2));
// ...
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
  'Content-Type: multipart/form-data;',
  // ...

您发送标头Content-Type: multipart/form-data,但数据编码为application/x-www-form-urlencodedhttp_build_query()}。

您要在第二个请求中发布的数据包含'localfile'=>'my_data.csv'。如果要在第二个请求上传文件,则内容类型正确(但您无需手动设置)。不要使用http_build_query(),而是将数组传递给CURLOPT_POSTFIELDSexplained in the documentation也是如此。

此外,对于文件上传,您必须在文件名前添加@,并确保curl能够找到该文件。最好的方法是使用完整的文件路径:

$post_array_2 = array(
    'localfile'    => '@'.__DIR__'/my_data.csv',
    'theater_mode' => 'normal'
);

上面的代码假定my_data.csv与PHP脚本位于同一目录中(不推荐)。您应该使用dirname()从脚本的目录导航到存储CSV文件的目录,以构成正确的路径。

正如文档还指出的那样,自PHP 5.5起,不推荐使用@前缀,您应该使用CURLFile类进行文件上传:

$post_array_2 = array(
    'localfile'    => new CURLFile(__DIR__'/my_data.csv'),
    'theater_mode' => 'normal'
);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post_array_2);

作为旁注,当您致电curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_ANY);时,表示允许curl与服务器协商身份验证方法。但是你也发送标题"Authorization: Basic ".base64_encode("$username:$password"),这会删除任何协商,因为它会强制Authorization: Basic

此外,为了取消联系,curl需要知道(用户,密码)组合。您应始终使用curl_setopt(CURLOPT_USERPWD, "$username:$password")告诉用户和密码。建议不要手动制作Authorization标题。

如果您确定Authorization: Basic是您需要的方法,那么您可以 使用curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC)

答案 1 :(得分:0)

您在帖子中看不到任何内容,因为您使用的是'Content-Type: multipart/form-data;',。只需删除它就可以了。

如果你想上传一个文件(即my_data.csv),你需要按照这种方式:

## change your file name as following in your param
'localfile'=> '@'.'./my_data.csv',

## after that remove http_build_query() from post
curl_setopt($ch, CURLOPT_POSTFIELDS, $post_array_2);

这会自动在帖子中添加标题multipart

您可以使用$_FILES变量查看上传的文件。

最后,您可以观察curl启用详细模式的内容。

curl_setopt($ch, CURLOPT_VERBOSE, true);

提示:使用Cookie时,请务必在每次curl_exec()之后关闭curl。否则,在您提出每个请求后,它都不会将内容写入cookie文件中!