PHP卷曲和饼干
我对PHP Curl和Cookie身份验证有一些问题 我有一个文件Connector.php,它对另一台服务器上的用户进行身份验证,并返回当前用户的cookie 问题是我想用curl对数千个用户进行身份验证,但它一次只对一个用户进行身份验证并保存cookie connector.php的代码如下:PHP卷曲和饼干,php,authentication,cookies,curl,Php,Authentication,Cookies,Curl,我对PHP Curl和Cookie身份验证有一些问题 我有一个文件Connector.php,它对另一台服务器上的用户进行身份验证,并返回当前用户的cookie 问题是我想用curl对数千个用户进行身份验证,但它一次只对一个用户进行身份验证并保存cookie connector.php的代码如下: <?php if(!count($_REQUEST)) { die("No Access!"); } //Core Url For Servi
<?php
if(!count($_REQUEST)) {
die("No Access!");
}
//Core Url For Services
define ('ServiceCore', 'http://example.com/core/');
//Which Internal Service Should Be Called
$path = $_GET['service'];
//Service To Be Queried
$url = ServiceCore.$path;
//Open the Curl session
$session = curl_init($url);
// If it's a GET, put the GET data in the body
if ($_GET['service']) {
//Iterate Over GET Vars
$postvars = '';
foreach($_GET as $key=>$val) {
if($key!='service') {
$postvars.="$key=$val&";
}
}
curl_setopt ($session, CURLOPT_POST, true);
curl_setopt ($session, CURLOPT_POSTFIELDS, $postvars);
}
//Create And Save Cookies
$tmpfname = dirname(__FILE__).'/cookie.txt';
curl_setopt($session, CURLOPT_COOKIEJAR, $tmpfname);
curl_setopt($session, CURLOPT_COOKIEFILE, $tmpfname);
curl_setopt($session, CURLOPT_HEADER, false);
curl_setopt($session, CURLOPT_RETURNTRANSFER, true);
curl_setopt($session, CURLOPT_FOLLOWLOCATION, true);
// EXECUTE
$json = curl_exec($session);
echo $json;
curl_close($session);
?>
您可以使用curl opt指定cookie文件。您可以为每个用户使用一个唯一的文件
curl_setopt( $curl_handle, CURLOPT_COOKIESESSION, true );
curl_setopt( $curl_handle, CURLOPT_COOKIEJAR, uniquefilename );
curl_setopt( $curl_handle, CURLOPT_COOKIEFILE, uniquefilename );
最好的处理方法是将您的请求逻辑粘贴到curl函数中,并将唯一的文件名作为参数传入
function fetch( $url, $z=null ) {
$ch = curl_init();
$useragent = isset($z['useragent']) ? $z['useragent'] : 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:10.0.2) Gecko/20100101 Firefox/10.0.2';
curl_setopt( $ch, CURLOPT_URL, $url );
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
curl_setopt( $ch, CURLOPT_AUTOREFERER, true );
curl_setopt( $ch, CURLOPT_FOLLOWLOCATION, true );
curl_setopt( $ch, CURLOPT_POST, isset($z['post']) );
if( isset($z['post']) ) curl_setopt( $ch, CURLOPT_POSTFIELDS, $z['post'] );
if( isset($z['refer']) ) curl_setopt( $ch, CURLOPT_REFERER, $z['refer'] );
curl_setopt( $ch, CURLOPT_USERAGENT, $useragent );
curl_setopt( $ch, CURLOPT_CONNECTTIMEOUT, ( isset($z['timeout']) ? $z['timeout'] : 5 ) );
curl_setopt( $ch, CURLOPT_COOKIEJAR, $z['cookiefile'] );
curl_setopt( $ch, CURLOPT_COOKIEFILE, $z['cookiefile'] );
$result = curl_exec( $ch );
curl_close( $ch );
return $result;
}
我用这个快速抓取。它包含url和一系列选项。您可以使用CURLOPT\u-COOKIEFILE
和CURLOPT\u-COOKIEJAR
为每个用户定义不同的cookie。为每个用户创建不同的文件,以便每个用户在远程服务器上都有自己的基于cookie的会话。首先使用tempnam()函数创建临时cookie:
$ckfile = tempnam ("/tmp", "CURLCOOKIE");
function CURL($url, $data = null, $method = 'GET', $cookie = null, $options = null, $retries = 3)
{
$result = false;
if ((extension_loaded('curl') === true) && (is_resource($curl = curl_init()) === true))
{
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_FAILONERROR, true);
curl_setopt($curl, CURLOPT_AUTOREFERER, true);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
if (preg_match('~^(?:DELETE|GET|HEAD|OPTIONS|POST|PUT)$~i', $method) > 0)
{
if (preg_match('~^(?:HEAD|OPTIONS)$~i', $method) > 0)
{
curl_setopt_array($curl, array(CURLOPT_HEADER => true, CURLOPT_NOBODY => true));
}
else if (preg_match('~^(?:POST|PUT)$~i', $method) > 0)
{
if (is_array($data) === true)
{
foreach (preg_grep('~^@~', $data) as $key => $value)
{
$data[$key] = sprintf('@%s', rtrim(str_replace('\\', '/', realpath(ltrim($value, '@'))), '/') . (is_dir(ltrim($value, '@')) ? '/' : ''));
}
if (count($data) != count($data, COUNT_RECURSIVE))
{
$data = http_build_query($data, '', '&');
}
}
curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
}
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, strtoupper($method));
if (isset($cookie) === true)
{
curl_setopt_array($curl, array_fill_keys(array(CURLOPT_COOKIEJAR, CURLOPT_COOKIEFILE), strval($cookie)));
}
if ((intval(ini_get('safe_mode')) == 0) && (ini_set('open_basedir', null) !== false))
{
curl_setopt_array($curl, array(CURLOPT_MAXREDIRS => 5, CURLOPT_FOLLOWLOCATION => true));
}
if (is_array($options) === true)
{
curl_setopt_array($curl, $options);
}
for ($i = 1; $i <= $retries; ++$i)
{
$result = curl_exec($curl);
if (($i == $retries) || ($result !== false))
{
break;
}
usleep(pow(2, $i - 2) * 1000000);
}
}
curl_close($curl);
}
return $result;
}
然后执行curl init witch将cookie保存为临时文件:
$ch = curl_init ("http://uri.com/");
curl_setopt ($ch, CURLOPT_COOKIEJAR, $ckfile);
curl_setopt ($ch, CURLOPT_RETURNTRANSFER, true);
$output = curl_exec ($ch);
$ch = curl_init ("http://somedomain.com/cookiepage.php");
curl_setopt ($ch, CURLOPT_COOKIEFILE, $ckfile);
curl_setopt ($ch, CURLOPT_RETURNTRANSFER, true);
$output = curl_exec ($ch);
或者使用临时文件中存储的cookie访问页面:
$ch = curl_init ("http://uri.com/");
curl_setopt ($ch, CURLOPT_COOKIEJAR, $ckfile);
curl_setopt ($ch, CURLOPT_RETURNTRANSFER, true);
$output = curl_exec ($ch);
$ch = curl_init ("http://somedomain.com/cookiepage.php");
curl_setopt ($ch, CURLOPT_COOKIEFILE, $ckfile);
curl_setopt ($ch, CURLOPT_RETURNTRANSFER, true);
$output = curl_exec ($ch);
这将初始化页面的cookie:
curl_setopt ($ch, CURLOPT_COOKIEFILE, $ckfile);
在处理一个类似的问题时,我结合了在web上遇到的大量资源,并添加了自己的cookie处理,然后创建了以下函数。希望这对其他人有用
function get_web_page( $url, $cookiesIn = '' ){
$options = array(
CURLOPT_RETURNTRANSFER => true, // return web page
CURLOPT_HEADER => true, //return headers in addition to content
CURLOPT_FOLLOWLOCATION => true, // follow redirects
CURLOPT_ENCODING => "", // handle all encodings
CURLOPT_AUTOREFERER => true, // set referer on redirect
CURLOPT_CONNECTTIMEOUT => 120, // timeout on connect
CURLOPT_TIMEOUT => 120, // timeout on response
CURLOPT_MAXREDIRS => 10, // stop after 10 redirects
CURLINFO_HEADER_OUT => true,
CURLOPT_SSL_VERIFYPEER => true, // Validate SSL Certificates
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_COOKIE => $cookiesIn
);
$ch = curl_init( $url );
curl_setopt_array( $ch, $options );
$rough_content = curl_exec( $ch );
$err = curl_errno( $ch );
$errmsg = curl_error( $ch );
$header = curl_getinfo( $ch );
curl_close( $ch );
$header_content = substr($rough_content, 0, $header['header_size']);
$body_content = trim(str_replace($header_content, '', $rough_content));
$pattern = "#Set-Cookie:\\s+(?<cookie>[^=]+=[^;]+)#m";
preg_match_all($pattern, $header_content, $matches);
$cookiesOut = implode("; ", $matches['cookie']);
$header['errno'] = $err;
$header['errmsg'] = $errmsg;
$header['headers'] = $header_content;
$header['content'] = $body_content;
$header['cookies'] = $cookiesOut;
return $header;
}
函数获取网页($url,$cookiesIn=''){
$options=array(
CURLOPT_RETURNTRANSFER=>true,//返回网页
CURLOPT_HEADER=>true,//除返回内容外,还返回头
CURLOPT_FOLLOWLOCATION=>true,//跟随重定向
CURLOPT_ENCODING=>“”,//处理所有编码
CURLOPT_AUTOREFERER=>true,//在重定向时设置referer
CURLOPT_CONNECTTIMEOUT=>120,//连接超时
CURLOPT_TIMEOUT=>120,//响应超时
CURLOPT_MAXREDIRS=>10,//在10次重定向后停止
CURLINFO_HEADER_OUT=>true,
CURLOPT_SSL_VERIFYPEER=>true,//验证SSL证书
CURLOPT_HTTP_VERSION=>CURL_HTTP_VERSION_1_1,
CURLOPT_COOKIE=>$cookiesIn
);
$ch=curl\u init($url);
curl_setopt_数组($ch$options);
$rough\u content=curl\u exec($ch);
$err=curl\u errno($ch);
$errmsg=curl\u error($ch);
$header=curl\u getinfo($ch);
卷曲关闭($ch);
$header\u content=substr($rough\u content,0,$header['header\u size']);
$body_content=trim(str_replace($header_content,,$rough_content));
$pattern=“#设置Cookie:\\s+(?[^=]+=[^;]+)#m”;
preg_match_all($pattern,$header_content,$matches);
$cookiesOut=内爆(“;”,$matches['cookie']);
$header['errno']=$err;
$header['errmsg']=$errmsg;
$header['headers']=$header\u内容;
$header['content']=$body\u content;
$header['cookies]=$cookiesOut;
返回$header;
}
在这里,您可以找到一些关于cURL&cookies的有用信息
您也可以像使用函数一样使用这个很好的方法:
$ckfile = tempnam ("/tmp", "CURLCOOKIE");
function CURL($url, $data = null, $method = 'GET', $cookie = null, $options = null, $retries = 3)
{
$result = false;
if ((extension_loaded('curl') === true) && (is_resource($curl = curl_init()) === true))
{
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_FAILONERROR, true);
curl_setopt($curl, CURLOPT_AUTOREFERER, true);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
if (preg_match('~^(?:DELETE|GET|HEAD|OPTIONS|POST|PUT)$~i', $method) > 0)
{
if (preg_match('~^(?:HEAD|OPTIONS)$~i', $method) > 0)
{
curl_setopt_array($curl, array(CURLOPT_HEADER => true, CURLOPT_NOBODY => true));
}
else if (preg_match('~^(?:POST|PUT)$~i', $method) > 0)
{
if (is_array($data) === true)
{
foreach (preg_grep('~^@~', $data) as $key => $value)
{
$data[$key] = sprintf('@%s', rtrim(str_replace('\\', '/', realpath(ltrim($value, '@'))), '/') . (is_dir(ltrim($value, '@')) ? '/' : ''));
}
if (count($data) != count($data, COUNT_RECURSIVE))
{
$data = http_build_query($data, '', '&');
}
}
curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
}
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, strtoupper($method));
if (isset($cookie) === true)
{
curl_setopt_array($curl, array_fill_keys(array(CURLOPT_COOKIEJAR, CURLOPT_COOKIEFILE), strval($cookie)));
}
if ((intval(ini_get('safe_mode')) == 0) && (ini_set('open_basedir', null) !== false))
{
curl_setopt_array($curl, array(CURLOPT_MAXREDIRS => 5, CURLOPT_FOLLOWLOCATION => true));
}
if (is_array($options) === true)
{
curl_setopt_array($curl, $options);
}
for ($i = 1; $i <= $retries; ++$i)
{
$result = curl_exec($curl);
if (($i == $retries) || ($result !== false))
{
break;
}
usleep(pow(2, $i - 2) * 1000000);
}
}
curl_close($curl);
}
return $result;
}
上面描述的解决方案,即使具有唯一的Cookie文件名,也会在规模上造成许多问题
我们必须用这个解决方案提供大量的身份验证,而我们的服务器因为高文件读写操作而停机
解决方案是使用Apache反向代理并完全忽略CURL请求
有关如何在Apache上使用代理的详细信息,请参见:
我解决了使用唯一PHPSESSID为不同用户创建不同cookie文件的问题<代码>$tmpfname=dirname(_文件__)。'/'.$\u COOKIE['PHPSESSID']..txt'如果有很多用户,这是个好主意吗?如果有很多用户,这是个坏主意。它会导致apache服务器崩溃。我用apache代理解决了这个问题。并且删除了我所有的CURL代码。当这个页面被很多用户使用(超过10000)时会怎么样?这不是服务器上的一个巨大负载吗?例如,如果大量用户试图同时访问该页面,而您在/tmp中已经有一些文件,该怎么办?PHP文档说:注意:如果PHP无法在指定的dir参数中创建文件,那么它将使用系统默认值。在NTFS上,如果指定的目录包含的文件超过65534个,也会发生这种情况。如果存储时间超过24小时,请删除cookie文件。将$ckfile的cookie数据单独存储,以便检查/tmp中的所有文件。3年后,对于像我这样的非PHP人员,您仍然是一个救生员。在阅读了大量的stackoverflow答案之后,这里有一个有序的解释。非常有用的代码。它起作用了。非常感谢。如果人们想要HTTP状态代码,请使用以下语法:$header['HTTP_code']@Doug,我已经检查了中代码的正则表达式\Set Cookie:\\s+(?[^=]+=[^;]+)\m
,正则表达式引擎解释这部分\\s+
为:\`匹配字符\字面上
s+`匹配字符的字面上(区分大小写)——这在正则表达式的这一部分不是一个错误吗,应该是\s+
(只有一个反斜杠)?@Igor,是因为在PHP中处理字符串时,\。因此,您需要两个斜杠来等于计算字符串中的一个斜杠(然后将用于正则表达式匹配)。从正则表达式的角度看,您是正确的,我只需要一个斜杠。