ตำแหน่งที่เชื่อถือได้ของคีย์คิวรี่ HTTP GET ซ้ำ


137

ฉันมีปัญหาในการค้นหาข้อมูลที่เชื่อถือได้เกี่ยวกับพฤติกรรมที่มีสตริงข้อความค้นหา HTTP GET ซ้ำกันเช่น

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

และโดยเฉพาะอย่างยิ่งหากมีการเก็บรักษาคำสั่งซื้อหรือไม่ ภาษาบนเว็บส่วนใหญ่จะสร้างอาเรย์ที่มีทั้ง foo และ bar ที่เชื่อมโยงกับคีย์ "field" แต่ฉันต้องการทราบว่ามีคำสั่งที่มีสิทธิ์ (เช่นใน RFC) เกี่ยวกับประเด็นนี้หรือไม่ RFC 3986มีส่วน3.4. Queryซึ่งอ้างถึงคู่ key = value แต่ไม่มีการพูดถึงวิธีการตีความลำดับและฟิลด์ที่ซ้ำกันและอื่น ๆ เรื่องนี้สมเหตุสมผลเนื่องจากมันขึ้นอยู่กับแบ็กเอนด์และไม่อยู่ในขอบเขตของ RFC นั้น ...

แม้ว่าจะมีมาตรฐานแบบพฤตินัยอยู่แล้ว แต่ฉันต้องการเห็นแหล่งข้อมูลที่เชื่อถือได้สำหรับเรื่องนี้


เคยสงสัยเรื่องนี้เช่นกัน อีกอย่างคือข้อมูลจำเพาะเกี่ยวกับการรวมพารามิเตอร์จากสตริงการสืบค้นกับเนื้อหาใน POST body
Thilo

ผู้คนบอกว่าไม่มีการรับประกันการสั่งซื้อ แต่เธรดนั้นเก่าและไม่มีใครสำรองไว้ แต่อย่างใด: coderanch.com/t/357197/Servlets/java/getParameterValues-order
Thilo

1
นอกเหนือจากเซิร์ฟเวอร์ที่รักษาลำดับของสตริงการสืบค้นแล้วยังมีคำถามเกี่ยวกับเบราว์เซอร์ที่ส่งพวกเขาในการสั่งซื้อ DOM (หรืออื่น ๆ คงที่)
Thilo

คำตอบ:


112

มีไม่มีสเป็คเป็นเกี่ยวกับเรื่องนี้ คุณสามารถทำสิ่งที่คุณชอบ

วิธีการทั่วไปรวมถึง: ได้รับครั้งแรกที่ได้รับครั้งสุดท้ายอาร์เรย์ของทั้งหมด, สตริงเข้าร่วมกับจุลภาคของทั้งหมด

สมมติว่าคำขอดิบคือ:

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

จากนั้นมีตัวเลือกต่าง ๆ สำหรับสิ่งที่request.query['tag']ควรให้ผลทั้งนี้ขึ้นอยู่กับภาษาหรือกรอบงาน:

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

12
ยิ่งไปกว่านั้นคำถามยังมีตัวเลือกของ ['ราง', 'ทับทิม'] (ลำดับที่แตกต่างกัน)
Thilo

2
เราสามารถทำสิ่งต่าง ๆ ได้มากมายอย่างแน่นอน
yfeldblum

7
.NET จะให้คุณเป็นอาร์เรย์ (ฉันไม่ได้ใส่ใจเกี่ยวกับการสั่งซื้อเมื่อฉันทดสอบนั้น) PHP จะให้คุณเสมอสุดท้ายและ Java (อย่างน้อยระบบที่ฉันทำงานด้วย Java) เสมอค่าแรก stackoverflow.com/questions/1809494/…
SimonSimCity

17
สิ่งนี้ขึ้นอยู่กับการโจมตีที่เรียกว่ามลพิษทางพารามิเตอร์ HTTP และได้รับการวิเคราะห์โดย OWASP: owasp.org/images/b/ba/AppsecEU09_CarettoniDiPaola_v0.8.pdf OWASP: owasp.org/images/b/ba/AppsecEU09_CarettoniDiPaola_v0.8.pdfที่หน้า 9 คุณจะพบรายชื่อ 20 ระบบและคำอธิบายวิธีที่พวกเขาจัดการ ปัญหานี้
SimonSimCity

1
@SimonSimCity นอกเหนือจากนั้น PHP จะสร้างอาร์เรย์จริง ๆ ถ้าคุณต่อท้ายวงเล็บเหลี่ยมพร้อมกับดัชนีทางเลือกเข้ากับชื่อพารามิเตอร์
Martin Ender

14

ฉันสามารถยืนยันได้ว่าสำหรับ PHP (อย่างน้อยในรุ่น 4.4.4 และใหม่กว่า) มันทำงานได้ดังนี้:

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

ผลลัพธ์ใน:

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

แต่

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

ผลลัพธ์ใน:

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

พฤติกรรมนี้เหมือนกันสำหรับข้อมูล GET และ POST


1
[]ต่อท้ายดูเหมือนว่าพฤติกรรมแปลกจริงๆ แต่ถ้าคุณพยายามที่จะส่งอาร์เรย์เป็นอาร์กิวเมนต์ผ่านของ jQuery .ajax()แล้วมันจะเพิ่มโดยอัตโนมัติให้คุณในทางเดียวกัน ดูเหมือนว่านี่คือเพื่อประโยชน์ของผู้ใช้ PHP
Ian Clark

4
@IanClark มันใช้งานง่ายสำหรับ PHP coders - ใน PHP ธรรมดาต่อ$foo[] = 1ท้ายอาร์เรย์ Django (Python) ก็ทำสิ่งเดียวกัน
Izkata

สามารถตรวจสอบกับ Apache Tomcat มันจะส่งกลับสตริงที่เชื่อมต่อกัน
Gaurav Ojha

8

คำตอบของ yfeldblum นั้นสมบูรณ์แบบ

แค่ทราบเกี่ยวกับพฤติกรรมที่ห้าที่ฉันสังเกตเห็นเมื่อเร็ว ๆ นี้: บนWindows Phone การเปิดแอปพลิเคชันที่มี uri พร้อมด้วยคีย์การสืบค้นที่ซ้ำกันจะส่งผลให้ NavigationFailed ด้วย:

System.ArgumentException: รายการที่มีคีย์เดียวกันได้ถูกเพิ่มไปแล้ว

System.Windows.Navigation.UriParsingHelper.InternalUriParseQueryStringToDictionary(Uri uri, Boolean decodeResults)ผู้กระทำผิดเป็น

ดังนั้นระบบจะไม่ยอมให้คุณจัดการในแบบที่คุณต้องการมันจะห้ามมัน คุณเหลือเพียงโซลูชันเดียวในการเลือกรูปแบบของคุณเอง (CSV, JSON, XML, ... ) และ uri-escape-it


2
ดูเหมือนว่าเป็นข้อบกพร่องภายในของฟังก์ชันนั้นแทนที่จะเป็นตัวเลือกการออกแบบ ฟังก์ชั่นอาจไม่ตรวจสอบคีย์ซ้ำในพจนานุกรมที่กำลังสร้าง แน่นอนว่าพจนานุกรมต้องใช้กุญแจที่เป็นเอกลักษณ์
gligoran

1
ดังนั้นเบราว์เซอร์ไคลเอ็นต์ - ไม่ใช่เซิร์ฟเวอร์ - กำลังโยนข้อผิดพลาดในสถานการณ์นี้หรือไม่ ดูเหมือนว่าจะเป็นข้อบกพร่อง ฉันสงสัยว่าข้อผิดพลาดนี้ยังคงมีอยู่ในปัจจุบันหรือไม่?
Jon Schneider

1
@JonSchneider ใช่ลูกค้ากำลังขว้างNavigationFailedURI เช่นนั้น แต่ยกโทษให้ฉันฉันลดลงการพัฒนา Windows (โทรศัพท์) หนึ่งเดือนหลังจากโพสต์นี้และฉันย้ายไป macOS (iOS) ดังนั้นฉันไม่สามารถช่วยได้อีกต่อไปในการติดตามปัญหานี้ในปัจจุบัน
Cœur

5

เฟรมเวิร์กส่วนใหญ่ (ทั้งหมด?) ไม่มีการรับประกันดังนั้นให้ถือว่าพวกเขาจะถูกส่งกลับในลำดับสุ่ม

ใช้แนวทางที่ปลอดภัยที่สุดเสมอ

ตัวอย่างเช่นอินเตอร์เฟส Java HttpServlet: ServletRequest.html # getParameterValues

แม้แต่เมธอดgetParameterMap ยังคงกล่าวถึงการเรียงลำดับพารามิเตอร์ใด ๆ (ลำดับของ java.util.Map iterator ไม่สามารถพึ่งพาได้เช่นกัน)


3

โดยทั่วไปแล้วค่าพารามิเตอร์ที่ซ้ำกันเช่น

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

ส่งผลให้พารามิเตอร์ queryString เดียวที่เป็นอาร์เรย์:

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

ฉันเห็นพฤติกรรมนี้ใน ASP, ASP.NET และ PHP4


ตรงนี้เป็นมาตรฐานความจริง แต่เท่าที่ฉันเห็นไม่มีการตัดสินใจที่มีสิทธิ์ในมัน เนื่องจากฉันไม่เชื่อในกรณีนี้ฉันจึงไม่สามารถค้นหามันได้
Stefano Borini

2
ใช่ทุกคนคงเคยเห็นพฤติกรรมนั้น คำถามคือถ้ามีการระบุจริง
Thilo

-1

ฉันมีคำถามเดียวกัน ฉันกำลังเขียนฟังก์ชั่นจาวาสคริปต์ในการแยกวิเคราะห์และทำให้เป็นสตริงแบบสอบถาม ฉันไม่ทราบว่าสตริงข้อความค้นหามีชื่อซ้ำกันหรือชื่อที่มีวงเล็บเช่น x [] = 1 & x [] = 2 เป็นมาตรฐานแม้ว่าบางภาษารองรับรูปแบบเหล่านี้

แต่ฉันพบว่า Chrome และ Firefox มี Class ใหม่ที่ชื่อว่าURLSeachParamsและรองรับเฉพาะรูปแบบที่ง่ายที่สุดname=valueเท่านั้น หากมีชื่อซ้ำกันในสตริงการสืบค้นgetวิธีการURLSearchParamsจะส่งกลับเฉพาะชื่อแรกเท่านั้น

โดยส่วนตัวแล้วอาจเป็นชื่อที่ง่ายที่สุดและไม่มีชื่อซ้ำกันจะปลอดภัยกว่าสำหรับอนาคต


1
หากมีชื่อซ้ำกันในสตริงการสืบค้นเมธอด get ของ URLSearchParams จะส่งกลับเฉพาะชื่อแรกเท่านั้น สิ่งนี้ไม่ถูกต้อง: คุณสามารถดึงค่าทั้งหมดเป็นอาร์เรย์โดยใช้URLSearchParams.getAll('x')
Blaise

@Blaise ขอบคุณมากฉันเข้าใจผิดเกี่ยวกับคุณสมบัติก่อนหน้านี้
LCB
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.