也许我只需要一双新鲜的眼睛......
我需要 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文件!