Vị trí có thẩm quyền của các khóa truy vấn HTTP GET trùng lặp


137

Tôi gặp khó khăn khi tìm thông tin có thẩm quyền về hành vi với các trường trùng lặp chuỗi truy vấn HTTP GET, như

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

và đặc biệt nếu thứ tự được giữ hay không. Hầu hết các ngôn ngữ hướng web tạo ra một mảng chứa cả foo và bar được liên kết với một "trường" chính, nhưng tôi muốn biết liệu có tồn tại tuyên bố có thẩm quyền hay không (ví dụ trên RFC) về điểm này. RFC 3986 có một phần 3.4. Query, đề cập đến các cặp key = value, nhưng không có gì được nói về cách diễn giải các thứ tự và các trường trùng lặp, v.v. Điều này có ý nghĩa, vì nó phụ thuộc vào phụ trợ, và không thuộc phạm vi của RFC đó ...

Mặc dù tiêu chuẩn thực tế tồn tại, tôi muốn thấy một nguồn có thẩm quyền cho nó, chỉ vì tò mò.


Đã tự hỏi về điều đó, quá. Một điều khác là thông số kỹ thuật về việc hợp nhất các tham số từ chuỗi truy vấn với các tham số trong phần thân POST.
Thilo

Ở trang trại mã, mọi người nói không có bảo đảm đặt hàng. Nhưng chủ đề đó đã cũ và không ai ủng hộ nó theo bất kỳ cách nào: coderanch.com/t/357197/Servlets/java/getParameterValues-order
Thilo

1
Ngoài máy chủ giữ thứ tự của chuỗi truy vấn, còn có câu hỏi về trình duyệt gửi chúng theo thứ tự DOM (hoặc một số cố định khác).
Thilo

Câu trả lời:


112

Không có thông số kỹ thuật về điều này. Bạn có thể làm những gì bạn thích.

Các cách tiếp cận điển hình bao gồm: đưa ra trước, đưa ra cuối cùng, mảng của tất cả, chuỗi tham gia với dấu phẩy của tất cả.

Giả sử yêu cầu thô là:

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

Sau đó, có nhiều tùy chọn khác nhau cho những gì request.query['tag']sẽ mang lại, tùy thuộc vào ngôn ngữ hoặc khung:

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

12
Thêm vào điểm của câu hỏi, cũng có tùy chọn ['rails', 'ruby'] (thứ tự khác nhau).
Thilo

2
Một người chắc chắn có thể làm một số lượng lớn các điều.
yfeldblum

7
.NET sẽ cung cấp cho bạn dưới dạng một mảng (tôi chưa quan tâm đến thứ tự khi tôi kiểm tra điều đó), PHP sẽ cung cấp cho bạn luôn là cuối cùng và Java (ít nhất là hệ thống tôi làm việc dựa trên Java) luôn là giá trị đầu tiên. stackoverflow.com/questions/1809494/
SimonSimCity

17
Điều này dựa trên một cuộc tấn công có tên là Ô nhiễm tham số HTTP và đã được phân tích bởi OWASP: owasp.org/images/b/ba/AppsecEU09_CarettoniDiPaola_v0.8.pdf Tại trang 9, bạn sẽ tìm thấy danh sách 20 hệ thống và mô tả cách họ xử lý vấn đề này.
SimonSimCity

1
@SimonSimCity ngoài ra, PHP thực sự sẽ tạo ra một mảng nếu bạn nối các dấu ngoặc vuông với một chỉ mục tùy chọn vào tên tham số.
Martin Ender

14

Tôi có thể xác nhận rằng đối với PHP (ít nhất là trong phiên bản 4.4.4 trở lên), nó hoạt động như thế này:

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

kết quả trong:

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

Nhưng

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

kết quả trong:

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

Hành vi này là giống nhau cho dữ liệu GET và POST.


1
Các []hậu tố có vẻ như hành vi thực sự kỳ lạ, nhưng nếu bạn cố gắng gửi một mảng như một cuộc tranh cãi qua jQuery .ajax(), sau đó nó sẽ tự động thêm chúng cho bạn trong cùng một cách. Có vẻ như điều này là vì lợi ích của người dùng PHP.
Ian Clark

4
@IanClark Nó trực quan với các lập trình viên PHP - trong PHP đơn giản, $foo[] = 1nối thêm vào một mảng. Django (Python) cũng làm điều tương tự.
Izkata

Có thể xác minh trên Apache Tomcat, nó trả về các chuỗi được nối bằng dấu phẩy.
Gaurav Ojha

8

Câu trả lời của yfeldblum là hoàn hảo.

Chỉ cần một lưu ý về hành vi thứ năm mà tôi nhận thấy gần đây: trên Windows Phone , việc mở một ứng dụng có uri với khóa truy vấn trùng lặp sẽ dẫn đến NavigationFails với:

System.ArgumentException: Một mục có cùng khóa đã được thêm vào.

Thủ phạm là System.Windows.Navigation.UriParsingHelper.InternalUriParseQueryStringToDictionary(Uri uri, Boolean decodeResults).

Vì vậy, hệ thống thậm chí sẽ không cho phép bạn xử lý nó theo cách bạn muốn, nó sẽ cấm nó. Bạn chỉ còn lại giải pháp duy nhất là chọn định dạng của riêng bạn (CSV, JSON, XML, ...) và uri-esc-it.


2
Đó dường như là một lỗi nội bộ của chức năng đó, hơn là một sự lựa chọn thiết kế. Hàm có lẽ không kiểm tra các khóa trùng lặp trong Từ điển mà nó đang tạo. Từ điển, tất nhiên, yêu cầu các phím duy nhất.
gligoran

1
Vì vậy, trình duyệt máy khách - không phải máy chủ - đang gặp lỗi trong tình huống này? Nó có vẻ như là một lỗi. Tôi tự hỏi nếu lỗi này vẫn còn tồn tại đến ngày hôm nay?
Jon Schneider

1
@JonSchneider Có, khách hàng đang NavigationFailedsử dụng URI đó. Nhưng, tha thứ cho tôi, tôi đã bỏ sự phát triển của Windows (Điện thoại) một tháng sau bài đăng này và tôi đã chuyển sang macOS (iOS), vì vậy tôi không thể giúp theo dõi vấn đề này ngày nay nữa.
Cœur

5

Hầu hết (tất cả?) Của các khung cung cấp không đảm bảo, vì vậy giả sử chúng sẽ được trả về theo thứ tự ngẫu nhiên.

Luôn luôn có cách tiếp cận an toàn nhất.

Ví dụ: giao diện java httpServlet: ServletRequest.html # getParameterValues

Ngay cả phương thức getParameterMap cũng không đề cập đến bất kỳ đề cập nào về thứ tự tham số (thứ tự của một trình lặp java.util.Map không thể dựa vào một trong hai.)


3

Thông thường, trùng lặp các giá trị tham số như

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

dẫn đến một tham số queryString duy nhất là một mảng:

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

Tôi đã thấy hành vi này trong ASP, ASP.NET và PHP4.


chính xác, đây là tiêu chuẩn thực tế, nhưng theo tôi thấy không có quyết định chính thức nào về nó. Vì tôi không tin đây là trường hợp, tôi chỉ không thể tìm thấy nó.
Stefano Borini

2
Vâng, có lẽ tất cả mọi người đã thấy hành vi đó. Câu hỏi là nếu điều đó thực sự được chỉ định ở đâu đó.
Thilo

-1

Tôi đã có cùng một câu hỏi. Tôi đang viết hàm javascript để phân tích và xâu chuỗi các truy vấn. Tôi không biết nếu một chuỗi truy vấn có tên trùng lặp hoặc tên có dấu ngoặc, chẳng hạn như x [] = 1 & x [] = 2, là tiêu chuẩn mặc dù một số ngôn ngữ hỗ trợ định dạng này.

Nhưng tôi thấy rằng Chrome và Firefox có một Class mới có tên URLSeachParamsvà Nó chỉ hỗ trợ định dạng đơn giản nhất name=value. Nếu có các tên trùng lặp trong chuỗi truy vấn, getphương thức URLSearchParamschỉ trả về tên đầu tiên.

Vì vậy, cá nhân, có thể một url tên đơn giản nhất và không trùng lặp sẽ an toàn hơn nhiều cho tương lai.


1
Nếu có các tên trùng lặp trong chuỗi truy vấn, phương thức get của URLSearchParams chỉ trả về tên đầu tiên. Điều này không chính xác: bạn có thể truy xuất tất cả giá trị dưới dạng một mảng bằng cách sử dụngURLSearchParams.getAll('x')
Blaise

@Blaise Cảm ơn bạn rất nhiều, tôi đã hiểu nhầm tính năng trước đây.
LCB
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.