cURL 未发送开机自检数据


cURL not sending POST data

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

我需要 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.'    ----  ';
}

错误出现在第二个请求上:

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-urlencoded (通过 http_build_query() (。

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

此外,对于文件上传,您必须在文件名前面放置一个@,并确保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) .

您在帖子中看不到任何内容,因为您使用的是'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()后关闭卷曲。 否则,在您发出每个请求后,它可能不会将内容写入cookie文件!