Logging in to HTTPS websites using PHP cURL

用PHP cURL登陆https网站可以按照以下步骤操作:

在你的php.ini配置文件中,取消注释掉这一行:extension=php_curl.dll

设置cURL接受所有的证书或者授权证书列表(其实可以设置为接受所有证书) (参阅http://unitstep.net/blog/2009/05/05/using-curl-in-php-to-access-https-ssltls-protected-sites/)

下面,你需要加载登录页面获取这个页面的cookie:

// Create temp file to store cookies
$ckfile = tempnam ("/tmp", "CURLCOOKIE"); 
 
// URL to login page
$url = "https://www.securesiteexample.com"; 
 
// Get Login page and its cookies and save cookies in the temp file
$ch = curl_init();
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // Accepts all CAs
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_COOKIEJAR, $ckfile); // Stores cookies in the temp file
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$output = curl_exec($ch);
现在你已经获取了登录页面的cookie,你可以把需要POST传递的值传递出去(请检查登录页面的代码,看看是不是有什么隐藏域的值也需要传递)
$fields = array(
'username' => 'yourusername',
'password' => 'yourpassword',
);
$fields_string = '';
foreach($fields as $key=>;$value) {
$fields_string .= $key . '=' . $value . '&';
}
rtrim($fields_string, '&');
 
// Post login form and follow redirects
$ch = curl_init();
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // Accepts all CAs
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, count($fields));
curl_setopt($ch, CURLOPT_POSTFIELDS, $fields_string);
curl_setopt($ch, CURLOPT_COOKIEFILE, $ckfile); //Uses cookies from the temp file
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); // 让cURL跟随页面跳转
$output = curl_exec($ch);

最后一步,你可以用已经获取的cookie来访问保护页面:

$url = "https://www.securesiteexample.com/loggedinpage.html";
$ch = curl_init();
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // Accepts all CAs
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_COOKIEFILE, $ckfile); //Uses cookies from the temp file
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$output = curl_exec($ch);

在cURL执行过后,应当注意的是,一定要及时清除COOKIE,否则很有可能引起数据错乱,尤其是在LOOP的时候。
对于COOKIE的解决办法,似乎有两种:一种办法是在生成COOKIE时,给其加上timestamp,Try appending a timestamp to your $url variable: $url.’?t=’.time()
这样做的好处是,每一次的COOKIE都不会混乱,但是,如果执行多次的话,COOKIE文件夹会无比overload
第二种办法,就是及时地清除文件夹下面的cookies了,似乎@unlink($cookiejar)并不是那么好用,可能是权限的问题,没有深入研究。就在每次调用完curl执行后,写一个函数清除cookie文件夹下的所有文件即可。如下:

function removeDir($dirName)
{
     if(!is_dir($dirName)) //如果传入的参数不是目录,则为文件,应将其删除
     {
     @unlink($dirName);//删除文件
       return false;
     }
     $handle = @opendir($dirName); //如果传入的参数是目录,则使用opendir将该目录打开,将返回的句柄赋值给$handle
     while(($file = @readdir($handle)) !== false) //这里明确地测试返回值是否全等于(值和类型都相同)FALSE,否则任何目录项的名称求值为 FALSE 的都会导致循环停止(例如一个目录名为“0”)。
     {
         if($file!='.'&&$file!='..') //在文件结构中,都会包含形如“.”和“..”的向上结构,但是它们不是文件或者文件夹
         {
         $dir = $dirName . '/' . $file; //当前文件$dir为文件目录+文件
         is_dir($dir)?removeDir($dir):@unlink($dir); //判断$dir是否为目录,如果是目录则递归调用reMoveDir($dirName)函数,将其中的文件和目录都删除;如果不是目录,则删除该文件
         }
     }
     closedir($handle);
}

需要的时候执行一次就好:

$dir="tmp";
removeDir($dir);

最近做application monitor的时候,最纠结的地方。唉,以是为记。网上只有少数人谈到清除cookie的问题,google上的人也没有给出几个可行的办法。不过相比之下,google还是比baidu靠谱多了。