Autorisierende Position doppelter HTTP-GET-Abfrageschlüssel

137

Ich habe Probleme beim Auffinden autorisierender Informationen zum Verhalten mit doppelten Feldern für HTTP-GET-Abfragezeichenfolgen, z

http://example.com/page?field=foo&field=bar 

und insbesondere, ob die Bestellung eingehalten wird oder nicht. Die meisten weborientierten Sprachen erzeugen ein Array, das sowohl foo als auch bar enthält, die einem Schlüsselfeld zugeordnet sind. Ich würde jedoch gerne wissen, ob zu diesem Punkt eine maßgebliche Aussage (z. B. in einem RFC) vorhanden ist. RFC 3986 hat einen Abschnitt 3.4. Query, der sich auf Schlüssel = Wert-Paare bezieht, aber es wird nichts darüber gesagt, wie Reihenfolge und doppelte Felder zu interpretieren sind und so weiter. Dies ist sinnvoll, da es vom Backend abhängig ist und nicht im Rahmen dieses RFC liegt ...

Obwohl es einen De-facto-Standard gibt, würde ich aus Neugier gerne eine maßgebliche Quelle dafür sehen.

Stefano Borini
quelle
Ich habe mich auch darüber gewundert. Die andere Sache ist die Spezifikation zum Zusammenführen der Parameter aus der Abfragezeichenfolge mit denen im POST-Body.
Thilo
Drüben auf der Code Ranch sagen die Leute, dass es keine Bestellgarantie gibt. Aber dieser Thread ist alt und niemand sichert ihn in irgendeiner Weise: coderanch.com/t/357197/Servlets/java/getParameterValues-order
Thilo
1
Zusätzlich dazu, dass der Server die Reihenfolge der Abfragezeichenfolge beibehält, gibt es auch die Frage, ob der Browser sie in DOM-Reihenfolge (oder einer anderen festen Reihenfolge) sendet.
Thilo

Antworten:

112

Es gibt keine Spezifikation dazu. Sie können tun, was Sie wollen.

Typische Ansätze sind: zuerst gegeben, zuletzt gegeben, Array von allen, String-Join mit Komma von allen.

Angenommen, die Rohanforderung lautet:

GET /blog/posts?tag=ruby&tag=rails HTTP/1.1
Host: example.com

Dann gibt es verschiedene Optionen für das, was request.query['tag']je nach Sprache oder Rahmen ergeben soll:

request.query['tag'] => 'ruby'
request.query['tag'] => 'rails'
request.query['tag'] => ['ruby', 'rails']
request.query['tag'] => 'ruby,rails'
Yfeldblum
quelle
12
Genauer gesagt gibt es auch die Option ['Schienen', 'Rubin'] (andere Reihenfolge).
Thilo
2
Man kann sicherlich eine Vielzahl von Dingen tun.
Yfeldblum
6
.NET gibt Ihnen als Array (ich habe mich nicht um die Reihenfolge gekümmert, als ich das getestet habe), PHP gibt Ihnen immer den letzten und Java (zumindest das System, mit dem ich basierend auf Java gearbeitet habe) immer den ersten Wert. stackoverflow.com/questions/1809494/…
SimonSimCity
17
Dies basiert auf einem Angriff namens HTTP Parameter Pollution und wurde von OWASP analysiert: owasp.org/images/b/ba/AppsecEU09_CarettoniDiPaola_v0.8.pdf Auf Seite 9 finden Sie eine Liste von 20 Systemen und eine Beschreibung ihrer Handhabung dieses Problem.
SimonSimCity
1
@SimonSimCity Darüber hinaus erstellt PHP tatsächlich ein Array, wenn Sie eckige Klammern mit einem optionalen Index an den Parameternamen anhängen.
Martin Ender
14

Ich kann bestätigen, dass es für PHP (zumindest in Version 4.4.4 und neuer) folgendermaßen funktioniert:

GET /blog/posts?tag=ruby&tag=rails HTTP/1.1
Host: example.com

Ergebnisse in:

request.query['tag'] => 'rails'

Aber

GET /blog/posts?tag[]=ruby&tag[]=rails HTTP/1.1
Host: example.com

Ergebnisse in:

request.query['tag'] => ['ruby', 'rails']

Dieses Verhalten ist für GET- und POST-Daten gleich.

SimonSimCity
quelle
1
Das []Suffix scheint ein wirklich seltsames Verhalten zu sein. Wenn Sie jedoch versuchen, ein Array als Argument über jQuery's zu senden .ajax(), werden diese automatisch auf dieselbe Weise für Sie hinzugefügt. Es sieht so aus, als ob dies den PHP-Benutzern zugute kommt.
Ian Clark
4
@IanClark Es ist intuitiv für PHP-Codierer - in einfachem PHP wird $foo[] = 1es an ein Array angehängt. Django (Python) macht das auch.
Izkata
Kann auf Apache Tomcat überprüfen, ob durch Kommas verkettete Zeichenfolgen zurückgegeben werden.
Gaurav Ojha
8

yfeldblums Antwort ist perfekt.

Nur ein Hinweis zu einem fünften Verhalten, das ich kürzlich bemerkt habe: Unter Windows Phone führt das Öffnen einer Anwendung mit einer URL mit einem doppelten Abfrageschlüssel zu NavigationFailed mit:

System.ArgumentException: Ein Element mit demselben Schlüssel wurde bereits hinzugefügt.

Der Schuldige ist System.Windows.Navigation.UriParsingHelper.InternalUriParseQueryStringToDictionary(Uri uri, Boolean decodeResults).

Das System lässt Sie also nicht einmal so damit umgehen, wie Sie es möchten, es verbietet es. Sie haben nur noch die einzige Lösung, um Ihr eigenes Format (CSV, JSON, XML, ...) und Uri-Escape-It auszuwählen.

Cœur
quelle
2
Das scheint eher ein interner Fehler dieser Funktion zu sein als eine Designentscheidung. Die Funktion wahrscheinlich sucht nicht nach doppelten Schlüsseln in dem Wörterbuch, das sie erstellt. Wörterbücher erfordern natürlich eindeutige Schlüssel.
Gligoran
1
Der Client-Browser - nicht der Server - gibt in dieser Situation einen Fehler aus? Es scheint ein Fehler zu sein. Ich frage mich, ob dieser Fehler heute noch besteht.
Jon Schneider
1
@ JonSchneider Ja, der Client wirft NavigationFailednach einer solchen URI. Aber verzeihen Sie mir, ich habe die Windows (Phone) -Entwicklung einen Monat nach diesem Beitrag eingestellt und bin zu macOS (iOS) gewechselt, sodass ich heutzutage nicht mehr anders kann, um dieses Problem zu verfolgen.
Cœur
5

Die meisten (alle?) Frameworks bieten keine Garantien. Nehmen Sie also an, dass sie in zufälliger Reihenfolge zurückgegeben werden.

Gehen Sie immer am sichersten vor.

Beispiel: Java-HttpServlet-Schnittstelle: ServletRequest.html # getParameterValues

Selbst die Methode getParameterMap lässt keine Erwähnung der Parameterreihenfolge aus (auf die Reihenfolge eines Iterators java.util.Map kann man sich auch nicht verlassen.)

Photodeus
quelle
3

In der Regel duplizieren Parameterwerte wie

http://example.com/page?field=foo&field=bar

führen zu einem einzelnen queryString-Parameter, der ein Array ist:

field[0]=='foo'
field[1]=='bar'

Ich habe dieses Verhalten in ASP, ASP.NET und PHP4 gesehen.

3Dave
quelle
Genau, dies ist der De-facto-Standard, aber meines Erachtens gibt es keine maßgebliche Entscheidung darüber. Da ich nicht glaube, dass dies der Fall ist, bin ich einfach unfähig, es zu finden.
Stefano Borini
2
Ja, wahrscheinlich hat jeder dieses Verhalten gesehen. Die Frage war, ob das tatsächlich irgendwo angegeben ist.
Thilo
-1

Ich hatte die gleiche Frage. Ich schreibe eine Javascript-Funktion, um Abfragen zu analysieren und zu stringifizieren. Ich weiß nicht, ob eine Abfragezeichenfolge doppelte Namen oder Namen in Klammern enthält, z. B. x [] = 1 & x [] = 2, obwohl einige Sprachen dieses Format unterstützen.

Aber ich finde, dass Chrome und Firefox eine neue Klasse namens haben URLSeachParamsund es nur das einfachste Format als unterstützt name=value. Wenn die Abfragezeichenfolge doppelte Namen enthält, gibt die getMethode URLSearchParamsnur den ersten zurück.

Persönlich ist eine einfachste und keine doppelte Namens-URL für die Zukunft viel sicherer.

LCB
quelle
1
Wenn die Abfragezeichenfolge doppelte Namen enthält, gibt die get-Methode von URLSearchParams nur den ersten zurück. Dies ist nicht korrekt: Sie können alle Werte als Array mitURLSearchParams.getAll('x')
Blaise
@Blaise Vielen Dank, ich habe das Feature schon einmal falsch verstanden.
LCB