2010-04-05 19 views
61

Todo a través de Internet, incluido incluso aquí en desbordamiento de pila, quienes afirman que una buena forma de comprobar si una solicitud es o no es AJAX para hacer lo siguiente:

if (strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') {...} 

Sin embargo, no veo $_SERVER['HTTP_X_REQUESTED_WITH'] en el official PHP documentation

Y cuando trato de hacer lo siguiente: se emite

echo $_SERVER['HTTP_X_REQUESTED_WITH']; 

Nada.

¿Estoy haciendo algo mal? Porque realmente me gustaría poder usar $_SERVER['HTTP_X_REQUESTED_WITH'] si está disponible.

Respuesta

17

$_SERVER Las claves que comienzan con HTTP_ se generan a partir de encabezados de solicitud HTTP. En este caso, el encabezado X-Requested-With.

+0

¿Todos los navegadores establecen este encabezado? Además, ¿cómo se establece este encabezado si se trata de una llamada AJAX? – Hank

+0

XHR puede enviar encabezados arbitrarios en una solicitud. –

+0

@Hank ¿Qué pasa con la llamada AJAX? ¿Crees que no utiliza una solicitud HTTP? ¿Cuál entonces? –

56

Las variables en $_SERVER no son realmente parte de PHP, por lo que no las encontrará en la documentación de PHP. Están preparados por el servidor web que los transfiere al lenguaje de scripting.

Hasta donde yo sé, el X-Requested-With es enviado por las funciones de Ajax de la mayoría de los Frameworks pero no todos (Dojo, por ejemplo, lo agregó hace solo dos años: #5801). Como tal, y teniendo en cuenta los comentarios de @bobince, es seguro decir que generalmente no es un método 100% confiable para determinar si una solicitud es una solicitud de AJAX o no.

La única forma 100% segura es enviar un indicador predefinido (por ejemplo, una variable GET) junto con la solicitud y para que la página de recepción compruebe la presencia de ese indicador.

+4

No creo que sea un método confiable tampoco. Las herramientas firewall/proxy pueden funcionar con él, y usted podría devolver la respuesta incorrecta a los usuarios proxy si no combina el uso de este encabezado con 'Vary: X-Requested-With' en la respuesta ... que a su vez se atornilla hasta la caché en IE. Mucha gente usa 'X-Requested-With', pero creo que es una idea terrible. Es mejor pasar un indicador en los parámetros de consulta para indicar que desea una respuesta XMLHttp-style (o JSON). – bobince

+1

@bobince ¿realmente es probable que un firewall se meta con él? Estoy construyendo una aplicación web que se utilizará principalmente desde una ubicación y ocasionalmente de forma remota. Sería realmente agradable poder abstraer el tipo de solicitud para que mi controlador pueda devolver una página entera o un fragmento de html dependiendo de si se trata de una solicitud de ajax ... – rgvcorley

+0

@rgvcorley: un proxy moderno típico no lo hará eliminar arbitrariamente los encabezados (aunque hay algunos crujientes desagradables usados ​​por las redes móviles). Pero el problema 'Vary' * te atornillará si tienes algo más que respuestas' nocache'. No vale la pena la molestia, por la pequeña mejora en la belleza de un encabezado; ir con un parámetro simple. – bobince

11

Este encabezado es una estandarización en curso de todas las bibliotecas de AJAX.

No estará documentado en la documentación de php per-se, sino en las diferentes bibliotecas de AJAX que configuran este encabezado. bibliotecas comunes no envían esta cabecera: jQuery, Mojo, Prototype, ...

lo general, estos biblioteca establece la cabecera usando

xhrobj.setRequestHeader("X-Requested-With", "XMLHttpRequest"); 
3
echo $_SERVER['HTTP_X_REQUESTED_WITH']; 

¿Qué esperabas de un código de este tipo? Supongamos que lo ejecuta directamente desde el navegador, sin utilizar la solicitud AJAX. Entonces, ¿cómo es que se puede establecer este encabezado?

Bueno, la respuesta a la máxima cuestión de la vida, el universo y todo: un HTTP sniffer! Consígase uno y olvide imprimir la variable $ _SERVER.

Firebug tiene uno, o es posible que desee utilizar el proxy Fiddler HTTP o el plugin LiveHTTPHeaders Mozilla. Estoy aburrido de hacer enlaces pero es fácil de googlear.

Por lo tanto, con el sniffer HTTP puede estar seguro de cualquier encabezado HTTP.

Tenga en cuenta que no puede evitar ningún "acceso directo" mediante el uso de XHR, ya que cada solicitud HTTP a su servidor ya es "directa".

+0

Desde el navegador y el XHR, nada salió – Hank

+0

¿cómo se puede saber con XHR? ¿Tu propiedad codificó una respuesta? –

27

no se olvide que se puede suplantar fácilmente cualquier cabecera con el enrollamiento al igual que

curl_setopt($ch,CURLOPT_HTTPHEADER,array("X-Requested-With : XMLHttpRequest")); 
+0

¿por qué usa una matriz aquí en lugar de cadena? – nssmart

1

También puede culpar a algunos errores del navegador - ver esta cuestión y su solución para Firefox

Firefox does not preserve custom headers during Ajax request redirect: an ASP.NET MVC solution

IE también tiene caching issue que es más grave que la detección del método de solicitud.

de todos modos tiene que añadir destructores de caché para evitar el almacenamiento en caché, ¿por qué no utilizar otra bandera para especificar la llamada AJAX - o más mejor podrá utilizar diferentes URL como http://ajax.mysite.com/endpoint/sevice?params

0

La mejor solución para asegurarse de si un HTTP la solicitud se envía realmente a través de AJAX utilizando la verificación SESSION, envía session_id en un parámetro get y comprueba esta sesión si está permitida o no.

4

Aquí está una función rápida con el ejemplo de uso:

function isXmlHttpRequest() 
{ 
    $header = isset($_SERVER['HTTP_X_REQUESTED_WITH']) ? $_SERVER['HTTP_X_REQUESTED_WITH'] : null; 
    return ($header === 'XMLHttpRequest'); 
} 

// example - checking our active call 
if(!isXmlHttpRequest()) 
{ 
    echo 'Not an ajax request'; 
} 
else 
{ 
    echo 'is an ajax request'; 
} 
1
$headers = apache_request_headers(); 
$is_ajax = (isset($headers['X-Requested-With']) && $headers['X-Requested-With'] == 'XMLHttpRequest'); 
+1

Esto no parece abordar la pregunta real. – Kenster

0

Estoy de acuerdo Pekka. No existe un método nativo confiable entre el anverso y el reverso que pueda detectar automáticamente si un cliente realmente llama a un punto final usando AJAX.

para mi propio uso, que tienen algunas de las formas principales para comprobar si un cliente solicita uno de mi punto final:

  1. puedo usar HTTP_X_REQUESTED_WITH cuando no estoy en el contexto dominios.

  2. en lugar de marcar "X-requested-with", estoy comprobando $ _SERVER ['HTTP_ORIGIN'] (que se envía desde la solicitud AJAX) con la intención de manejar permisos de dominio cruzado. La mayoría de las veces, la razón principal por la que estoy comprobando si una solicitud es una solicitud de AJAX, es especialmente debido a los permisos de dominio cruzado, usando este código PHP: header ('Access-Control-Allow-Origin:'. $ _ SERVER [' HTTP_ORIGIN ']); // Si este "HTTP_ORIGIN" está en mi lista blanca

  3. mis API esperan que el cliente explique, en algunos casos, el tipo de datos (JSON, HTML, etc.) en una variable GET o POST. Por ejemplo, verifico si $ _REQUEST ['ajax'] no está vacío o es igual a un valor esperado.

Cuestiones relacionadas