php - curlopt_cookiejar
Curl y cookies de PHP (6)
Tengo algún problema con PHP Curl and Cookies Authentication.
Tengo un archivo Connector.php que autentica usuarios en otro servidor y devuelve cookies con el usuario actual.
El problema es que quiero autenticar a miles de usuarios con curl, pero autentica y guarda COOKIES solo para un usuario a la vez.
el código para connector.php es este:
<?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);
?>
Aquí está el proceso de autenticación:
- El usuario ingresa el nombre de usuario y la contraseña: Connector.php? Service = logon & user_name = user32 & user_pass = 123
- Connector.php? Service = logosessionInfo esto devuelve información sobre el usuario en función de las cookies guardadas anteriormente con el servicio de inicio de sesión.
El problema es que este código guarda Cookie en un archivo para un usuario y no puede manejar la autenticación de múltiples usuarios.
Al trabajar con un problema similar, creé la siguiente función después de combinar muchos recursos que encontré en la web y agregar mi propio manejo de cookies. Espero que esto sea útil para otra persona.
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;
}
Aquí puede encontrar información útil sobre cURL & cookies http://docstore.mik.ua/orelly/webprog/pcook/ch11_04.htm .
También puede usar este método bien hecho https://github.com/alixaxel/phunction/blob/master/phunction/Net.php#L89 como una función:
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;
}
Y pasa esto como el parámetro $cookie
:
$cookie_jar = tempnam(''/tmp'',''cookie'');
Las soluciones que se describen arriba, incluso con nombres únicos de CookieFile, pueden causar muchos problemas en la escala.
Tuvimos que realizar muchas autenticaciones con esta solución y nuestro servidor se cayó debido a las altas acciones de escritura de lectura de archivos.
La solución para esto fue usar Apache Reverse Proxy y omitir todas las solicitudes de CURL.
Detalles sobre cómo usar Proxy en Apache se pueden encontrar aquí: https://httpd.apache.org/docs/2.4/howto/reverse_proxy.html
Primero crea una cookie temporal usando la función tempnam ():
$ckfile = tempnam ("/tmp", "CURLCOOKIE");
Luego de ejecutar el curl init, la cookie de bruja se guarda como un archivo temporal:
$ch = curl_init ("http://uri.com/");
curl_setopt ($ch, CURLOPT_COOKIEJAR, $ckfile);
curl_setopt ($ch, CURLOPT_RETURNTRANSFER, true);
$output = curl_exec ($ch);
O visite datos de cookies donde se almacena información temporal:
$ch = curl_init ("http://somedomain.com/cookiepage.php");
curl_setopt ($ch, CURLOPT_COOKIEFILE, $ckfile);
curl_setopt ($ch, CURLOPT_RETURNTRANSFER, true);
$output = curl_exec ($ch);
Esto cargará la página de inicio de la cookie:
curl_setopt ($ch, CURLOPT_COOKIEFILE, $ckfile);
Puede definir diferentes cookies para cada usuario con CURLOPT_COOKIEFILE
y CURLOPT_COOKIEJAR
. Cree un archivo diferente para cada usuario, de modo que cada uno tenga su propia sesión basada en cookies en el servidor remoto.
Puede especificar el archivo de cookie con una opción curl. Puede usar un archivo único para cada usuario.
curl_setopt( $curl_handle, CURLOPT_COOKIESESSION, true );
curl_setopt( $curl_handle, CURLOPT_COOKIEJAR, uniquefilename );
curl_setopt( $curl_handle, CURLOPT_COOKIEFILE, uniquefilename );
La mejor manera de manejarlo sería pegar la lógica de su solicitud en una función curl y simplemente pasar el nombre único del archivo como parámetro.
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;
}
Lo uso para tomas rápidas. Toma la url y una variedad de opciones.