Existiert $ _SERVER ['HTTP_X_REQUESTED_WITH'] in PHP oder nicht?

68

Überall im Internet, auch hier bei Stack Overflow, geben die Leute an, dass eine gute Möglichkeit, um zu überprüfen, ob eine Anfrage AJAX ist oder nicht, Folgendes ist:

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

Ich sehe jedoch nicht $_SERVER['HTTP_X_REQUESTED_WITH']in der offiziellen PHP-Dokumentation

Und wenn ich Folgendes versuche:

echo $_SERVER['HTTP_X_REQUESTED_WITH'];

Es wird nichts ausgegeben.

Mache ich etwas falsch? Weil ich wirklich gerne verwenden kann, $_SERVER['HTTP_X_REQUESTED_WITH']wenn es verfügbar ist.

Strang
quelle

Antworten:

62

Die Variablen in $_SERVERsind nicht wirklich Teil von PHP, weshalb Sie sie nicht in der PHP-Dokumentation finden. Sie werden vom Webserver vorbereitet, der sie an die Skriptsprache weiterleitet.

Soweit ich weiß, ist die X-Requested-With wird das von den Ajax-Funktionen der meisten wichtigen Frameworks gesendet, aber nicht von allen (Dojo hat es beispielsweise erst vor zwei Jahren hinzugefügt: # 5801 ). Unter Berücksichtigung der Kommentare von @bobince kann man mit Sicherheit sagen, dass dies im Allgemeinen keine 100% zuverlässige Methode ist, um festzustellen, ob eine Anfrage eine AJAX-Anfrage ist oder nicht.

Die einzige 100% sichere Möglichkeit besteht darin, ein vordefiniertes Flag (z. B. eine GET-Variable) zusammen mit der Anforderung zu senden und die empfangende Seite auf das Vorhandensein dieses Flags zu überprüfen.

Pekka
quelle
4
Ich denke auch nicht, dass es eine zuverlässige Methode ist. Firewall- / Proxy-Tools können sich damit herumschlagen, und Sie könnten die falsche Antwort an Proxy-Benutzer zurückgeben, wenn Sie die Verwendung dieses Headers nicht mit Vary: X-Requested-Withder Antwort kombinieren ... was wiederum das Cacheing im IE vermasselt. Viele Leute benutzen es X-Requested-With, aber ich denke, es ist eine schreckliche Idee. Übergeben Sie besser ein Flag in den Abfrageparametern, um zu signalisieren, dass Sie eine Antwort im XMLHttp-Stil (oder JSON) wünschen.
Bobince
1
@ Bobince ist es wirklich so wahrscheinlich, dass eine Firewall damit herumspielen wird? Ich erstelle eine Web-App, die hauptsächlich von einem Ort und gelegentlich aus der Ferne verwendet wird. Es wäre wirklich schön, von der Art der Anfrage abstrahieren zu können, damit mein Controller eine ganze Seite oder ein HTML-Snippet zurückgeben kann, je nachdem, ob es sich um eine Ajax-Anfrage handelt ...
rgvcorley
@rgvcorley: Ein typischer moderner Proxy entfernt Header nicht willkürlich (es gibt jedoch einige böse knarrende, kaputte, die von Mobilfunknetzen verwendet werden). Aber das VaryProblem wird mit Ihnen schrauben, wenn Sie alles andere als nocacheAntworten haben. Der Aufwand lohnt sich nicht, da sich die Schönheit eines Headers nur geringfügig verbessert. gehe mit einem einfachen Parameter.
Bobince
Danke für die Antwort - ja du hast recht. Ich denke, für diesen kleinen zusätzlichen Aufwand einer GET-Variablen haben Sie den Vorteil zu wissen, dass sie garantiert funktioniert!
Rgvcorley
4
Dojo ist KEIN Rahmen !! Es ist eine Bibliothek. Und jQuery ist auch eine Bibliothek . Leider hat sich das Wort "Framework" zu einem Schlagwort entwickelt, das oft falsch verwendet wird.
Sk8erPeter
27

Vergessen Sie nicht, dass Sie mit cURL jeden Header leicht fälschen können

curl_setopt($ch,CURLOPT_HTTPHEADER,array("X-Requested-With : XMLHttpRequest"));
J. Michael Wilson
quelle
Warum verwenden Sie hier ein Array anstelle eines Strings?
Nssmart
18

$_SERVERSchlüssel, die mit beginnen, HTTP_werden aus HTTP-Anforderungsheadern generiert. In diesem Fall der X-Requested-WithHeader.

Ignacio Vazquez-Abrams
quelle
Setzen alle Browser diesen Header? Wie wird dieser Header gesetzt, wenn es sich um einen AJAX-Aufruf handelt?
Hank
XHR kann beliebige Header in einer Anfrage senden.
Ignacio Vazquez-Abrams
@Hank Was ist los mit AJAX Anruf? Sie denken, es verwendet keine HTTP-Anfrage? Welches dann?
Ihr gesunder Menschenverstand
1
Ich versuche zu verhindern, dass Leute direkt auf meinen Webdienst zugreifen, erlaube aber XHR
Hank
9
@Hank XHR von "normalen" Anfragen zu unterscheiden ist als Sicherheitsmaßnahme absolut unbrauchbar, da jeder eine XHRequest problemlos simulieren kann. Sie müssen Ihre Ajax-Skripte mit soliden Authentifizierungsmaßnahmen schützen (oder was auch immer Sie bereits für Ihre Hauptanwendung eingerichtet haben).
Pekka
16

Dieser Header ist eine laufende Standardisierung aller AJAX-Bibliotheken.

Es wird nicht in der PHP-Dokumentation an sich dokumentiert, sondern in den verschiedenen AJAX-Bibliotheken, die diesen Header setzen. Allgemeine Bibliotheken haben diesen Header gesendet: jQuery, Mojo, Prototype, ...

Normalerweise setzen diese Bibliotheken den Header mit

xhrobj.setRequestHeader("X-Requested-With", "XMLHttpRequest");
Jerome WAGNER
quelle
4

Hier ist eine kurze Funktion mit Beispielverwendung:

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';
}
tfont
quelle
Dies beantwortet die Frage überhaupt nicht. Es sind solche Codefragmente, nach denen das OP fragt. Er möchte wissen, warum dies funktioniert, dh woher es $_SERVER['HTTP_X_REQUESTED_WITH']kommt, wo es eingestellt ist und ob / warum wir uns wirklich darauf verlassen können.
Osullic
3
echo $_SERVER['HTTP_X_REQUESTED_WITH'];

Was haben Sie von einem solchen Code erwartet? Angenommen, Sie führen es direkt über den Browser aus und verwenden keine AJAX-Anforderung. Wie kommt es, dass dieser Header gesetzt werden kann?

Nun, die Antwort auf die ultimative Frage des Lebens, des Universums und alles - ein HTTP-Sniffer ! Holen Sie sich eine und vergessen Sie das Drucken der Variablen $ _SERVER.

Firebug hat einen, oder Sie möchten möglicherweise den Fiddler HTTP-Proxy oder das LiveHTTPHeaders Mozilla-Plugin verwenden. Es ist mir langweilig, Links zu erstellen, aber es wird leicht gegoogelt.

Mit dem HTTP-Sniffer können Sie also sicher sein, dass es jemals einen HTTP-Header gibt.

Beachten Sie, dass Sie mit XHR keinen "direkten Zugriff" verhindern können, da jede HTTP-Anforderung an Ihren Server bereits "direkt" ist.

Ihr gesunder Menschenverstand
quelle
Sowohl vom Browser als auch von XHR wurde nichts ausgegeben
Hank
1

Sie können auch einige Browserfehler beschuldigen - siehe diese Frage und ihre Lösung für Firefox

Firefox behält während der Ajax-Anforderungsumleitung keine benutzerdefinierten Header bei: eine ASP.NET MVC-Lösung

IE hat auch Caching-Problem das schwerwiegender ist als die Erkennung der Anforderungsmethode.

Sie müssen ohnehin Cache-Busters hinzufügen, um das Caching zu vermeiden. Warum also nicht ein anderes Flag verwenden, um den Ajax-Aufruf anzugeben? Oder besser, Sie können eine andere URL wie http://ajax.mysite.com/endpoint/sevice?params verwenden

EGL 2-101
quelle
0

Die beste Lösung, um sicherzustellen, dass eine HTTP-Anfrage wirklich über AJAX gesendet wird, ist die SESSION-Prüfung. Sie senden session_id in einem get-Parameter und überprüfen diese Sitzung, ob dies zulässig ist oder nicht!

Der böse Denker
quelle
0
$headers = apache_request_headers();
$is_ajax = (isset($headers['X-Requested-With']) && $headers['X-Requested-With'] == 'XMLHttpRequest');
widerrufen
quelle
2
Dies scheint die eigentliche Frage nicht zu beantworten.
Kenster
0

Ich stimme Pekka zu. Es gibt keine zuverlässige native Methode zwischen Vorder- und Rückseite, mit der automatisch erkannt werden kann, ob ein Client mithilfe von AJAX tatsächlich einen Endpunkt aufruft.

Für meinen eigenen Gebrauch habe ich einige Hauptmethoden, um zu überprüfen, ob ein Client einen meiner Endpunkte anfordert:

  1. Ich kann HTTP_X_REQUESTED_WITH verwenden, wenn ich mich nicht im domänenübergreifenden Kontext befinde.

  2. Anstatt "X-request-with" zu überprüfen, überprüfe ich $ _SERVER ['HTTP_ORIGIN'] (das von einer AJAX-Anforderung gesendet wird), um domänenübergreifende Berechtigungen zu verarbeiten. Der Hauptgrund, warum ich prüfe, ob eine Anfrage eine AJAX-Anfrage ist, liegt hauptsächlich in domänenübergreifenden Berechtigungen, die diesen PHP-Code verwenden: header ('Access-Control-Allow-Origin:'. $ _ SERVER [' HTTP_ORIGIN ']); // Wenn dieses "HTTP_ORIGIN" in meiner weißen Liste ist

  3. Meine APIs erwarten vom Client, dass in einigen Fällen der Datentyp (JSON, HTML usw.) in eine GET- oder POST-Variable explizit angegeben wird. Zum Beispiel überprüfe ich, ob $ _REQUEST ['ajax'] nicht leer ist oder einem erwarteten Wert entspricht.

FragBis
quelle
0

Sie müssen es speziell in Ihrem Ajax-Anforderungsobjekt festlegen (dh, wenn Sie kein Framework wie jQuery verwenden), sondern in Javascript. wie so:

xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");

Wo xhr ist Ihr Anfrageobjekt?

Dann PHPwird es nun $_SERVERwie folgt empfangen und in die globale Variable gesetzt :

$_SERVER['HTTP_X_REQUESTED_WITH']

Andernfalls ist $ _SERVER ['HTTP_X_REQUESTED_WITH'] immer null.

Hinweis : Stellen Sie in Ihrem Javascript sicher, dass Sie Header festlegen, nachdem die Anforderung geöffnet ist. Ich meine nach xhr.open()Methode.

Nicholas Mberev
quelle