У меня есть некоторые проблемы с PHP Curl и Cookies Authentication.
У меня есть файл Connector.php, который проверяет подлинность пользователей на другом сервере и возвращает cookie с текущим пользователем.
Проблема в том, что я хочу, чтобы аутентифицировать тысячи пользователей с curl, но он аутентифицирует и сохраняет COOKIES только для одного пользователя за раз.
код для connector.php:
<?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); ?>
Вот процесс аутентификации:
Проблема в том, что этот код сохраняет Cookie в одном файле для одного пользователя и не может обрабатывать множественную аутентификацию пользователя.
Вы можете указать файл cookie с помощью curl opt. Вы можете использовать уникальный файл для каждого пользователя.
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-адрес и набор параметров.
При работе с аналогичной проблемой я создал следующую функцию после объединения большого количества ресурсов, с которыми я столкнулся в сети, и добавления моей собственной обработки файлов 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; }
Сначала создайте временный файл cookie с помощью функции tempnam ():
$ckfile = tempnam ("/tmp", "CURLCOOKIE");
Затем выполнение 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);
Или посетите данные cookie, где хранится временная информация:
$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);
Здесь вы можете найти полезную информацию о cURL & cookies http://docstore.mik.ua/orelly/webprog/pcook/ch11_04.htm .
Вы также можете использовать этот хорошо выполненный метод https://github.com/alixaxel/phunction/blob/master/phunction/Net.php#L89 как функцию:
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
:
$cookie_jar = tempnam('/tmp','cookie');
Вы можете определить разные файлы cookie для каждого пользователя с помощью CURLOPT_COOKIEFILE
и CURLOPT_COOKIEJAR
. Создавайте разные файлы для каждого пользователя, чтобы каждый из них имел свой собственный сеанс на основе файлов cookie на удаленном сервере.
Решения, которые описаны выше, даже с уникальными именами CookieFile, могут вызвать множество проблем в масштабе.
Мы должны были обслуживать множество аутентификаций с помощью этого решения, и наш сервер опустился из-за высокой активности чтения файлов.
Решением для этого было использование Apache Reverse Proxy и вообще отказаться от запросов CURL.
Подробнее о том, как использовать прокси-сервер в Apache, можно найти здесь: https://httpd.apache.org/docs/2.4/howto/reverse_proxy.html