也许我只需要一双新鲜的眼睛......
我需要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.' ---- ';
}
答案 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-urlencoded
(http_build_query()
}。
您要在第二个请求中发布的数据包含'localfile'=>'my_data.csv'
。如果要在第二个请求上传文件,则内容类型正确(但您无需手动设置)。不要使用http_build_query()
,而是将数组传递给CURLOPT_POSTFIELDS
,explained 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文件中!