使用PHP模拟POST&卷曲

时间:2011-02-07 19:54:43

标签: php curl libcurl

我正在尝试根据我在Firefox中看到来自Live HTTP标头的内容来模拟对网站的POST。

以下是Firefox插件日志的复制/粘贴:

  

POST / context?tab =登录HTTP / 1.1
  主持人:网站
用户代理:   Mozilla / 5.0(X11; U; Linux i686;   EN-US; rv:1.9.2.13)Gecko / 20101206   Ubuntu / 10.10(特立独行)   Firefox / 3.6.13
接受:   text / html的,应用/ XHTML + xml的,应用/ XML; Q = 0.9, / 的; Q = 0.8
  Accept-Language:en-us,en; q = 0.5
  Accept-Encoding:gzip,deflate
  接收字符集:   ISO-8859-1,utf-8; Q = 0.7,*; Q = 0.7
  保持活力:115
连接:   keep-alive
推荐人:referer
  Cookie:fontsize = 2;   JSESSIONID = 0000pXE_BK7TjZFzEyNHqOKzXz2:-1
  内容类型:   应用程序/ x-WWW窗体-urlencoded
  内容长度:46
  登录ID =密码&安培;密码=密码&安培;登录名=登录

POST后紧接着的响应:

  

HTTP / 1.1 302找到
位置:   网站/背景?标签= p00689
  内容 - 语言:en-US
  设置Cookie:   JSESSIONID = 0000oaKlIeeDRWkX5YCiJu5v1lM:-1;   路径= /
转移编码:   chunked
日期:2011年2月7日星期一   格林威治标准时间14:15:21服务器:WebSphere   Application Server / 6.1
到期:   1994年12月1日星期四格林威治标准时间16:00:00   Cache-Control:no-cache =“set-cookie,   设置COOKIE2"

根据我的测试,重定向到

的响应
  

网站/上下文?标签= p00689

表示用户已通过身份验证,一切正常。

然而,当试图通过PHP& cURL,我被重定向到一个页面,通知用户他们的会话已经超时。

以下是代码:

// Provider only likes Firefox
$agent = "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.2.13) Gecko/20101206 Ubuntu/10.10 (maverick) Firefox/3.6.13";

ini_set("user_agent", $agent);

// Cookie
$cookie = tempnam("/tmp", "curlcookie");

// Post everything that was posted to me.
$fields = $_POST;

foreach($fields as $key=>$value)
{
        $fields_string .= "$key=$value&";
}

$fields_string = substr($fields_string, 0, strlen($fields_string) - 1);

// Custom headers
$headers = array(
        "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
        "Accept-Language: en-us,en;q=0.5",
        "Accept-Encoding: gzip,deflate",
        "Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7",
        "Keep-Alive: 115",
        "Connection: keep-alive");

// cURL options
$ch = curl_init("website");

curl_setopt($ch, CURLOPT_REFERER, "referer");
curl_setopt($ch, CURLOPT_HEADER, 1);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $fields_string);
curl_setopt($ch, CURLOPT_COOKIEJAR, $cookie);
curl_setopt($ch, CURLOPT_COOKIEFILE, $cookie);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, false);
curl_setopt($ch, CURLOPT_MAXREDIRS, 1);
curl_setopt($ch, CURLINFO_HEADER_OUT, true);
curl_setopt($ch, CURLOPT_USERAGENT, $agent);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

$output = curl_exec($ch);
$header  = curl_getinfo($ch);

curl_close($ch);

// Debugging junk
echo nl2br($header["request_header"]);
echo "<br/><br/>Output:<br/><br/>$output";

该脚本的输出如下:

  

POST / context?tab =登录HTTP / 1.1
  User-Agent:User-Agent:Mozilla / 5.0   (X11; U; Linux i686; en-US;   rv:1.9.2.13)Gecko / 20101206   Ubuntu / 10.10(特立独行)   Firefox / 3.6.13
主持人:网站
  Pragma:no-cache
推荐人:   引用者:接受:   text / html的,应用/ XHTML + xml的,应用/ XML; Q = 0.9, / 的; Q = 0.8
  Accept-Language:en-us,en; q = 0.5
  Accept-Encoding:gzip,deflate
  接收字符集:   ISO-8859-1,utf-8; Q = 0.7,*; Q = 0.7
  保持活力:115
连接:   保持活力
内容长度:   46
内容类型:   应用程序/ x-WWW窗体-urlencoded
  
  登录ID =用户名和安培;密码=密码&安培;登录名=登录

     


输出:

HTTP / 1.1 302
  发现
  当前位置:网站/上下文选项卡= p00697
  内容 - 语言:en-US Set-Cookie:
  JSESSIONID = 0000Tl8NL1Hg2dbNv_PEnq-bbvr:-1;
  Path = / Set-Cookie:
  JSESSIONID = 0000Zue58y1tXg3tt4XjB8exXw6:-1;
  Path = / Transfer-Encoding:chunked
  日期:星期一,2011年2月7日19:18:20 GMT
  服务器:WebSphere Application
  Server / 6.1到期:1994年12月1日星期四   格林威治标准时间16:00:00缓存控制:
  无缓存=“设置的cookie,
  设置COOKIE2"

根据我发布的内容,有什么明显的遗漏吗?我接下来应该尝试什么?这些请求在语义上看起来是一样的;我不确定我做错了什么。

1 个答案:

答案 0 :(得分:1)

突出的一点是以下代码行:

$cookie = tempnam("/tmp", "curlcookie");

现在如果无法创建文件,那么tempnam将返回false,这意味着以下代码行:

curl_setopt($ch, CURLOPT_COOKIEJAR, $cookie);
curl_setopt($ch, CURLOPT_COOKIEFILE, $cookie);

完全没有设置,你应该将cookie文件保存在与执行脚本相同的目录中。

接下来是:

$fields = $_POST;
foreach($fields as $key=>$value)
{
   $fields_string .= "$key=$value&";
}
$fields_string = substr($fields_string, 0, strlen($fields_string) - 1);

您不需要这样做,因为CURLOPT_POSTFIELDS接受一个数组,所以您应该可以这样做:

curl_setopt($ch, CURLOPT_POSTFIELDS, $_POST);

这将确保正确解析实体。

我还认为您可以删除ini_set,因为file_get_contentsfopen等原生函数都是如此,所以仔细检查一行:

ini_set("user_agent", $agent);

另外,我会检查是否已经从主页面设置了一个cookie,例如index.php,因为该站点可能阻止来自直接带有数据的登录页面的来源的请求。