web-dev-qa-db-ger.com

Die URL-Codierung für externe Links führt auf dem Nginx-Server zu '% 3F' und '% 3D'

Ich habe ein Problem mit meinem Server. Ich habe vier eingehende Links zu verschiedenen Sites meiner dynamischen Webseite erhalten, die ungefähr so ​​aussehen:

myurl.com/default/Site%3Fid%3D13

Sie sollten so aussehen:

myurl.com/default/Site?id=13

Ich weiß, dass dieser %3F eine Escape-Sequenz für das ?-Zeichen und der %3D eine Escape-Sequenz für das Gleichheitszeichen ist. Aber ich bekomme eine Fehlermeldung 400, wenn ich diese Links benutze. Was kann ich dagegen tun?

Die vier Links beziehen sich auf verschiedene Websites, und ich stelle mir vor, dass es mit der Zeit weitere solche Links geben wird. Ein Fix für alle wäre also perfekt.

12
user3082653

Genau dieselbe Frage wurde vor ungefähr einem Jahr auf der Mailingliste von nginx-ru gestellt:

http://mailman.nginx.org/pipermail/nginx-ru/2013-February/050200.html

Die hilfreichste Antwort von Nginx, Inc, Mitarbeiter/Entwickler, Валентин Бартенев:

http://mailman.nginx.org/pipermail/nginx-ru/2013-February/050209.html

Sie können den Artikel in Ihrem Browser als Hintergrundbild anzeigen oder den Artikel in Ihrem Browser als Hintergrundbild anzeigen. Weitere Informationen zum Ort und zur Lage des Hotels.

Übersetzung:

Wenn die Anfrage in einer solchen Form eingeht, sind dies nicht mehr die Argumente, sondern der Name der angeforderten Datei. Eine andere Sache ist, dass, wie dokumentiert, der Standortabgleich gegen einen normalisierten URI durchgeführt wird.

Sein Lösungsvorschlag, übersetzt in das Beispiel aus der Frage hier bei SO, wäre dann:

location /default/Site? {
    rewrite \?(.*)$ /default/Site?$1? last;
}

location = /default/Site {
    [...]
}
8
cnst

Das folgende Beispiel leitet alle falsch aussehenden Anforderungen (definiert als ? im angeforderten Dateinamen - codiert als %3F in der Anforderung) unabhängig von der URL in weniger falsch aussehende um.

(Bitte beachten Sie, dass Sie, wie an anderer Stelle zu Recht empfohlen, diese falsch geformten Links nicht erhalten sollten. Verwenden Sie sie daher als letzten Ausweg - nur, wenn Sie die falsch geformten Links ansonsten nicht korrigieren können und Sie das wissen solche Anfragen werden von gültigen Agenten versucht.)

server {
    listen      [::]:80;
    server_name localhost;

    rewrite     ^/([^?]*)\?(.*)$    /$1?$2?     permanent;
    location / {
        return  200 "id is $arg_id\n";
    }
}

Dies ist ein Beispiel für die Funktionsweise: Wenn eine falsch aussehende Anforderung angetroffen wird, wird ein Korrekturversuch mit einer 301 Moved Permanently-Antwort mit einem vermeintlich korrekten Locationname__-Antwortheader durchgeführt, wodurch der Browser die Anforderung automatisch an den neu bereitgestellten Speicherort erneut ausgibt :

opti# curl -6v "http://localhost/default/Site%3Fid%3D13"
* About to connect() to localhost port 80 (#0)
*   Trying ::1...
* connected
* Connected to localhost (::1) port 80 (#0)
> GET /default/Site%3Fid%3D13 HTTP/1.1
> User-Agent: curl/7.26.0
> Host: localhost
> Accept: */*
>
< HTTP/1.1 301 Moved Permanently
< Server: nginx/1.4.1
< Date: Wed, 15 Jan 2014 17:09:25 GMT
< Content-Type: text/html
< Content-Length: 184
< Location: http://localhost/default/Site?id=13
< Connection: keep-alive
<
<html>
<head><title>301 Moved Permanently</title></head>
<body bgcolor="white">
<center><h1>301 Moved Permanently</h1></center>
<hr><center>nginx/1.4.1</center>
</body>
</html>
* Connection #0 to Host localhost left intact
* Closing connection #0

Beachten Sie, dass bei korrekt aussehenden Anforderungen keine Korrekturversuche durchgeführt werden:

opti# curl -6v "http://localhost/default/Site?id=13"
* About to connect() to localhost port 80 (#0)
*   Trying ::1...
* connected
* Connected to localhost (::1) port 80 (#0)
> GET /default/Site?id=13 HTTP/1.1
> User-Agent: curl/7.26.0
> Host: localhost
> Accept: */*
>
< HTTP/1.1 200 OK
< Server: nginx/1.4.1
< Date: Wed, 15 Jan 2014 17:09:30 GMT
< Content-Type: application/octet-stream
< Content-Length: 9
< Connection: keep-alive
<
id is 13
* Connection #0 to Host localhost left intact
* Closing connection #0
1
cnst

Die URL ist vollkommen gültig. Die darin enthaltenen Escape-Zeichen sind nur die Escape-Zeichen. Welches ist völlig in Ordnung.

Der Zweck ist, dass Sie tatsächlich einen Anforderungsnamen (in den meisten Fällen entsprechend dem Dateinamen auf dem Datenträger) haben können, der Site?id=13 und nicht Site ist, und der Rest als Abfragezeichenfolge.

Ich würde es für eine schlechte Praxis halten, Zeichen in einem Dateinamen zu haben, der dies erforderlich macht. In URL-Argumenten kann dies jedoch durchaus erforderlich sein.

Trotzdem ist die Anforderungs-URL gültig und wahrscheinlich nicht so, wie Sie es möchten. Was folglich nahelegt, dass Sie den Fehler korrigieren sollten, wenn jemand die falsche URL gefunden hat.

Ich verstehe nicht wirklich, warum Sie einen Fehler 400 erhalten; Sie sollten lieber eine Fehlermeldung 404 erhalten. Dies hängt jedoch von Ihrem Setup ab.

Es gibt auch Fälle, insbesondere bei Nginx, in denen zumeist ganze URLs und URL-Teile über mehrere Ebenen weitergegeben werden (z. B. Reverse-Proxys, Abgleichen regulärer Ausdrücke von der URL und Verwenden dieser als Variablen usw.), in denen ein solcher Fehler auftreten kann. Um dies zu überprüfen und zu beheben, müssen wir jedoch mehr über Ihr Setup erfahren.

0
The Surrican