instalar - su php no soporta curl
cURL funciona desde la Terminal, pero no desde PHP (4)
Me estoy encontrando con un problema bastante extraño.
Intento iniciar sesión en una instalación remota de Moodle utilizando Curl desde PHP.
Tengo un comando Curl, que funciona perfectamente en la Terminal.
Cuando traduzco lo mismo en PHP, funciona, pero simplemente no inicia sesión. El mismo valor exacto que inicia sesión exitosamente a través de la terminal, de alguna manera activa el sistema de inicio de sesión a través de PHP y no inicia sesión. En cambio, devuelve la página de inicio de sesión nuevamente.
Mi comando cURL (sección de datos omitida ya que tiene mi nombre de usuario y contraseña):
curl ''http://moodle.tsrs.org/login/index.php''
-H ''Pragma: no-cache''
-H ''Origin: http://moodle.tsrs.org''
-H ''Accept-Encoding: gzip, deflate''
-H ''Accept-Language: en-US,en;q=0.8''
-H ''User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.65 Safari/537.36''
-H ''Content-Type: application/x-www-form-urlencoded''
-H ''Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8''
-H ''Cache-Control: no-cache''
-H ''Referer: http://moodle.tsrs.org/login/index.php''
-H ''Cookie: MoodleSession=ngcidh028m37gm8gbdfe07mvs7; MOODLEID_=%25F1%25CD%2519D%25B2k%25FE%251D%25EFH%25E5t%25B1%2503%258E; MoodleSessionTest=NhzaTNij6j; _ga=GA1.2.925953522.1416155774; _gat=1; __utmt=1; __utma=147409963.925953522.1416155774.1416642544.1416692798.3; __utmb=147409963.1.10.1416692798; __utmc=147409963; __utmz=147409963.1416155774.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none)''
-H ''Connection: keep-alive''
El código PHP correspondiente:
function login() {
$username = $_POST[''username''];
$password = $_POST[''password''];
if(!isset($_POST[''username'']) || !isset($_POST[''password''])) {
echo "No login data received";
return;
}
$creq = curl_init();
$data = array(''username'' => $username, ''password'' => $password, ''testcookies''=> ''1'');
$headers = array(''Pragma: no-cache'', ''Origin: http://moodle.tsrs.org'', ''Accept-Encoding: '', ''Accept-Language: en-US,en;q=0.8'', ''User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.65 Safari/537.36'', ''Content-Type: application/x-www-form-urlencoded'', ''Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8'', ''Cache-Control: no-cache'', ''Cookie: MoodleSession=ngcidh028m37gm8gbdfe07mvs7; MOODLEID_=%25F1%25CD%2519D%25B2k%25FE%251D%25EFH%25E5t%25B1%2503%258E; MoodleSessionTest=NhzaTNij6j; _ga=GA1.2.925953522.1416155774; _gat=1; __utmt=1; __utma=147409963.925953522.1416155774.1416642544.1416692798.3; __utmb=147409963.1.10.1416692798; __utmc=147409963; __utmz=147409963.1416155774.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none)'', ''Connection: keep-alive'' );
curl_setopt_array($creq, array(
CURLOPT_URL => ''http://moodle.tsrs.org/login/index.php'',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_ENCODING => '''',
CURLINFO_HEADER_OUT => true,
CURLOPT_POSTFIELDS => $data,
CURLOPT_HTTPHEADER => $headers,
CURLOPT_FOLLOWLOCATION => false
));
$output = curl_exec($creq);
echo print_r(curl_getinfo($creq));
echo "/n" . $output . "/n";
}
Y la salida de curlinfo:
Array
(
[url] => http://moodle.tsrs.org/login/index.php
[content_type] => text/html; charset=utf-8
[http_code] => 200
[header_size] => 541
[request_size] => 945
[filetime] => -1
[ssl_verify_result] => 0
[redirect_count] => 0
[total_time] => 1.462409
[namelookup_time] => 0.002776
[connect_time] => 0.330766
[pretransfer_time] => 0.330779
[size_upload] => 365
[size_download] => 8758
[speed_download] => 5988
[speed_upload] => 249
[download_content_length] => -1
[upload_content_length] => 365
[starttransfer_time] => 0.694866
[redirect_time] => 0
[certinfo] => Array
(
)
[primary_ip] => 125.22.33.149
[redirect_url] =>
[request_header] => POST /login/index.php HTTP/1.1
Host: moodle.tsrs.org
Pragma: no-cache
Origin: http://moodle.tsrs.org
Accept-Language: en-US,en;q=0.8
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.65 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Cache-Control: no-cache
Cookie: MoodleSession=ngcidh028m37gm8gbdfe07mvs7; MOODLEID_=%25F1%25CD%2519D%25B2k%25FE%251D%25EFH%25E5t%25B1%2503%258E; MoodleSessionTest=NhzaTNij6j; _ga=GA1.2.925953522.1416155774; _gat=1; __utmt=1; __utma=147409963.925953522.1416155774.1416642544.1416692798.3; __utmb=147409963.1.10.1416692798; __utmc=147409963; __utmz=147409963.1416155774.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none)
Connection: keep-alive
Content-Length: 365
Expect: 100-continue
Content-Type: application/x-www-form-urlencoded; boundary=----------------------------83564ee60d56
)
¿Alguien sabe alguna razón posible para esto? Intenté cambiar la cookie codificada con COOKIEFILE y COOKIEJAR, pero no cambia nada.
Lo más probable es que su problema esté relacionado con el encabezado HTTP. Expect: 100-continue
enviando cURL de forma predeterminada para cada solicitud POST.
El encabezado Expect: 100-continue
se utiliza en las solicitudes POST que contienen big data cuando el cliente no está seguro de que el servidor acepte dicha solicitud. En este caso, el cliente primero envía la solicitud con solo encabezados, incluido Expect: 100-continue
y, si la respuesta del servidor es exitosa, envíe la misma solicitud con el cuerpo (datos POST).
El problema es que no todos los servidores web manejan este encabezado correctamente. En tales casos, enviar este encabezado no es deseado.
La solución se elimina manualmente. Expect
encabezado envíe encabezados pasando la array(''Expect:'')
a la opción CURLOPT_HTTPHEADER
. En su caso, simplemente puede agregar la cadena ''Esperar:'' a la matriz $headers
:
$headers[] = ''Expect:'';
Sospecho que su primer intento de usar el comando curl es usar el método GET en el archivo index.php. Te sugiero que habilites --trace-ascii
en tu primera solicitud de curl en la línea de comando y veas si la página está haciendo o no una solicitud GET. En caso afirmativo, debe cambiar su script PHP que está utilizando el método POST. Si cambia el CURLOPT_POST a falso, el script PHP debería funcionar.
Esto podría haber sido depurado mejor al ver todo lo que realmente fue hecho por cURL. Esto se hace agregando el indicador detallado al comando: -v
.
$ curl localhost/login [...] -v
Podemos obtener el mismo resultado del curl de PHP agregando la opción CURLOPT_VERBOSE
. Tenga en cuenta que al agregar esta línea, está instruyendo a cURL que envíe la misma información a STDOUT; no se devolverá y el contenido no se enviará al navegador, por lo que debe ser depurado en el terminal.
curl_setopt($curl, CURLOPT_VERBOSE, 1);
Al hacerlo de esta manera, puede obtener un resultado consistente y comparable de ambas solicitudes HTTP, debería verse así:
POST / HTTP/1.1
Host: localhost:3000
Pragma: no-cache
Origin: http://moodle.tsrs.org
Accept-Language: en-US,en;q=0.8
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.65 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Cache-Control: no-cache
Cookie: MoodleSession=ngcidh028m37gm8gbdfe07mvs7; MOODLEID_=%25F1%25CD%2519D%25B2k%25FE%251D%25EFH%25E5t%25B1%2503%258E; MoodleSessionTest=NhzaTNij6j; _ga=GA1.2.925953522.1416155774; _gat=1; __utmt=1; __utma=147409963.925953522.1416155774.1416642544.1416692798.3; __utmb=147409963.1.10.1416692798; __utmc=147409963; __utmz=147409963.1416155774.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none)
Connection: keep-alive
Content-Length: 250
Expect: 100-continue
Content-Type: application/x-www-form-urlencoded; boundary=------------------------b4d79f17a3887f2d
< HTTP/1.1 100 Continue
< HTTP/1.1 200 OK
< X-Powered-By: Express
< Content-Type: application/json; charset=utf-8
< Content-Length: 2
< ETag: W/"2-mZFLkyvTelC5g8XnyQrpOw"
< Date: Thu, 22 Dec 2016 19:13:40 GMT
< Connection: keep-alive
Izquierda: línea de comando cURL como se proporciona en la pregunta (con indicador extra -v
)
Derecha: PHP cURL como se publicó en la pregunta (con CURLOUT_VERBOSE
habilitado)
Como puede ver, los encabezados no son lo mismo, y esto lo deja en claro. A la invocación de PHP le faltan los encabezados Accept-Encoding
y Referer
.
Si eso no aparecía, intentemos cambiar algunas configuraciones más de cURL en PHP a los valores predeterminados originales de cURL.
Internamente, PHP opta por anular algunos valores predeterminados en cURL sin decírselo. Si bien estas configuraciones deberían estar bien, vamos a cambiarlas restableciéndolas explícitamente a los valores predeterminados de cURL:
curl_setopt($curl, CURLOPT_DNS_CACHE_TIMEOUT, 60);
curl_setopt($curl, CURLOPT_DNS_USE_GLOBAL_CACHE, 0);
curl_setopt($curl, CURLOPT_MAXREDIRS, -1);
curl_setopt($curl, CURLOPT_NOSIGNAL, 0);
Use http_build_query
en la matriz $data
antes de pasar a curl para evitar Content-Type: application/x-www-form-urlencoded; boundary=---
Content-Type: application/x-www-form-urlencoded; boundary=---
. Esto también garantiza codificar cualquier carácter especial de la contraseña.
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
Reforme sus solicitudes curl de la siguiente manera:
Realice una solicitud GET a la página de inicio de sesión señalando un archivo de cookie en $cookies = ''/tmp/some/dir/xyz.cookie.txt''
. Asegúrese de usar la ruta completa para el nombre de la cookie. Y luego cierre el mango curl. Esto almacenará la cookie en el archivo de cookies.
$creq = curl_init();
curl_setopt_array($creq, array(
CURLOPT_URL => ''http://moodle.tsrs.org/login/index.php'',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => '''',
CURLINFO_HEADER_OUT => true,
CURLOPT_HTTPHEADER => $headers,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_COOKIEJAR => $cookies // save cookie
));
$output = curl_exec($creq);
curl_close($creq);
Ahora realice la solicitud POST con la segunda solicitud curl. Esta vez, señale el mismo archivo de cookies con la opción COOKIEFILE.
$creq = curl_init();
curl_setopt_array($creq, array(
CURLOPT_URL => ''http://moodle.tsrs.org/login/index.php'',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_ENCODING => '''',
CURLINFO_HEADER_OUT => true,
CURLOPT_POSTFIELDS => http_build_query ($data),
CURLOPT_HTTPHEADER => $headers,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_COOKIEJAR => $cookies, // save cookie
CURLOPT_COOKIEFILE => $cookies // load cookie
);
$output = curl_exec($creq);
curl_close($creq);
En ocasiones, el servidor puede buscar la cookie cuando se realiza una solicitud de inicio de sesión (para asegurarse de que la solicitud se produjo después de visitar la página de inicio de sesión).