การเข้ารหัสพารามิเตอร์การสืบค้น URL ใน Java


109

หนึ่งเข้ารหัสพารามิเตอร์การสืบค้นเพื่อไปที่ url ใน Java ได้อย่างไร ฉันรู้ว่านี่เป็นคำถามที่ชัดเจนและถูกถามไปแล้ว

มีรายละเอียดปลีกย่อยสองประการที่ฉันไม่แน่ใจ:

  1. ควรเข้ารหัสช่องว่างใน url เป็น "+" หรือเป็น "% 20"? ใน chrome ถ้าฉันพิมพ์ "http://google.com/foo=?bar me" chrome จะเปลี่ยนเป็นการเข้ารหัสด้วย% 20
  2. จำเป็น / ถูกต้องหรือไม่ในการเข้ารหัสโคลอน ":" เป็น% 3B Chrome ไม่

หมายเหตุ:

  • java.net.URLEncoder.encodeดูเหมือนจะไม่ได้ผลดูเหมือนว่าจะมีการส่งแบบฟอร์มสำหรับการเข้ารหัสข้อมูล ตัวอย่างเช่นเข้ารหัสพื้นที่+แทน%20และเข้ารหัสโคลอนซึ่งไม่จำเป็น
  • java.net.URI ไม่เข้ารหัสพารามิเตอร์การค้นหา

คำถามนี้มีประโยชน์: stackoverflow.com/questions/444112/…
Alex Black

2
โครงสร้างของส่วนการสืบค้นขึ้นอยู่กับเซิร์ฟเวอร์แม้ว่าส่วนใหญ่จะคาดหวังapplication/x-www-form-urlencodedคู่คีย์ / ค่า ดูข้อมูลเพิ่มเติมได้ที่นี่: copyrightargumentexception.blogspot.com/2009/12/…
McDowell

คำตอบ:


128

java.net.URLEncoder.encode(String s, String encoding)สามารถช่วยได้เช่นกัน application/x-www-form-urlencodedมันเป็นไปตามรูปแบบการเข้ารหัสแบบ HTML

URLEncoder.encode(query, "UTF-8");

ในทางกลับกันการเข้ารหัสเปอร์เซ็นต์ (หรือที่เรียกว่าการเข้ารหัส URL ) จะเข้ารหัสพื้นที่ด้วย%20. โคลอนเป็นอักขระที่สงวนไว้ดังนั้น:จะยังคงเป็นโคลอนหลังจากเข้ารหัสแล้ว


3
ฉันบอกว่าฉันไม่คิดว่าจะเข้ารหัส url แต่มันเข้ารหัสข้อมูลที่จะส่งผ่านแบบฟอร์มแทน ความคิดเห็น?
Alex Black

นั่นเป็นเพราะURLEncoderสอดคล้องกับapplication/x-www-form-urlencodedรูปแบบ MIME (ซึ่งเป็นการเข้ารหัสรูปแบบ HTML ที่ถูกต้อง) ฉันคิดว่านั่นไม่ใช่สิ่งที่คุณกำลังมองหา
Buhake Sindi

6
ฉันลงเอยด้วยการใช้ URLEncoder.encode และแทนที่ "+" ด้วย "% 20"
Alex Black

2
มันเข้ารหัสเครื่องหมายทับเป็น "% 2F" ไม่ควรปล่อยให้ URL เป็นเครื่องหมายทับหรือไม่
golimar

6
@golimar ไม่มันไม่ควร คุณควรให้ค่าพารามิเตอร์เท่านั้นไม่ใช่ URL ทั้งหมด http://example.com/?url=http://example.com/?q=c&sort=nameลองพิจารณาตัวอย่าง ควรเข้ารหัส&sort=nameหรือไม่? ไม่มีวิธีแยกแยะมูลค่าจาก URL นั่นคือเหตุผลที่แท้จริงว่าทำไมคุณถึงต้องมีการเข้ารหัสค่าตั้งแต่แรก
Pijusn

15

แก้ไข: URIUtilไม่มีให้บริการในเวอร์ชันล่าสุดอีกต่อไปคำตอบที่ดีกว่าที่Java - เข้ารหัส URLหรือโดย Mr.Sindi ในชุดข้อความนี้


URIUtilของ Apache httpclient มีประโยชน์มากแม้ว่าจะมีทางเลือกอื่นอยู่บ้าง

URIUtil.encodeQuery(url);

ตัวอย่างเช่นเข้ารหัสพื้นที่เป็น "+" แทนที่จะเป็น "% 20"

ทั้งสองมีความถูกต้องสมบูรณ์ในบริบทที่เหมาะสม แม้ว่าคุณต้องการจริงๆคุณสามารถเปลี่ยนสตริงได้


ฉันจะต้องเห็นด้วย ใช้ HttpClient คุณจะมีความสุขมากขึ้น
DaShaun

ดูมีแนวโน้มมีลิงค์โดยบังเอิญ? ฉัน googling แต่พบหลายอย่าง
อเล็กซ์แบล็ก

1
วิธีนี้ดูเหมือนจะไม่มีอยู่ใน HttpClient 4.1? hc.apache.org/httpcomponents-client-ga/httpclient/apidocs/org/…
Alex Black

@ อเล็กซ์อืมมันน่ารำคาญฉันใช้กิจวัตรนั้นมาโดยตลอดและได้ผลลัพธ์ที่ดี แนวคิดอย่างหนึ่งคือการคว้าซอร์สโค้ดจากรีลีส 3 เนื่องจากตอนนี้เห็นได้ชัดว่าพวกเขาไม่ต้องการรักษามันอีกต่อไป
โยฮันSjöberg

1
URIUtil.encodeWithinQueryคือสิ่งที่คุณจะใช้เข้ารหัสพารามิเตอร์การค้นหาแต่ละรายการซึ่งเป็นสิ่งที่คำถามเดิมดูเหมือนจะถาม
Jesse Glick

13

ขออภัย URLEncoder.encode () ไม่สร้างการเข้ารหัสเปอร์เซ็นต์ที่ถูกต้อง (ตามที่ระบุในRFC 3986 )

URLEncoder.encode () เข้ารหัสทุกอย่างได้ดียกเว้นพื้นที่ถูกเข้ารหัสเป็น "+" ตัวเข้ารหัส Java URI ทั้งหมดที่ฉันพบจะเปิดเผยเฉพาะเมธอดสาธารณะในการเข้ารหัสคิวรีแฟรกเมนต์ส่วนพา ธ และอื่น ๆ - แต่อย่าเปิดเผยการเข้ารหัส "ดิบ" นี่เป็นเรื่องที่น่าเสียดายเนื่องจาก Fragment และ Query ได้รับอนุญาตให้เข้ารหัส Space เป็น + ดังนั้นเราจึงไม่ต้องการใช้มัน เส้นทางได้รับการเข้ารหัสอย่างถูกต้อง แต่ถูก "ทำให้เป็นมาตรฐาน" ก่อนดังนั้นเราจึงไม่สามารถใช้สำหรับการเข้ารหัส "ทั่วไป" ได้เช่นกัน

ทางออกที่ดีที่สุดที่ฉันคิดได้:

return URLEncoder.encode(raw, "UTF-8").replaceAll("\\+", "%20");

หากreplaceAll()ช้าเกินไปสำหรับคุณฉันคิดว่าทางเลือกคือการม้วนตัวเข้ารหัสของคุณเอง ...

แก้ไข: ฉันมีรหัสนี้ที่นี่ก่อนซึ่งไม่ได้เข้ารหัส "?", "&", "=" อย่างถูกต้อง:

//don't use - doesn't properly encode "?", "&", "="
new URI(null, null, null, raw, null).toString().substring(1);

+เป็นการเข้ารหัสพื้นที่ที่ถูกต้องอย่างสมบูรณ์แบบ
Lawrence Dol

@LawrenceDol เป็นเรื่องจริง แต่บางครั้ง+อาจตีความผิด - ลองดูที่ C # blogs.msdn.microsoft.com/yangxind/2006/11/08/…
Lu55

นี้. ฉันเปรียบเทียบทางเลือกต่างๆกับencodeURIComponentเอาต์พุตวิธีการของ Javascript และนี่เป็นการจับคู่แบบตรงทั้งหมดสำหรับสิ่งที่ฉันพยายาม (คำค้นหาที่มีช่องว่างอักขระพิเศษภาษาตุรกีและภาษาเยอรมัน)
Utku Özdemir

8

ไม่จำเป็นต้องเข้ารหัสโคลอนเป็น% 3B ในการสืบค้นแม้ว่าการทำเช่นนั้นจะไม่ผิดกฎหมาย

URI         = scheme ":" hier-part [ "?" query ] [ "#" fragment ]
query       = *( pchar / "/" / "?" )
pchar         = unreserved / pct-encoded / sub-delims / ":" / "@"
unreserved    = ALPHA / DIGIT / "-" / "." / "_" / "~"
pct-encoded   = "%" HEXDIG HEXDIG
sub-delims    = "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "="

ดูเหมือนว่าช่องว่างที่เข้ารหัสเปอร์เซ็นต์เท่านั้นที่ถูกต้องเนื่องจากฉันสงสัยว่าช่องว่างนั้นเป็น ALPHA หรือ DIGIT

ดูข้อกำหนด URIสำหรับรายละเอียดเพิ่มเติม


แต่การทำเช่นนี้สามารถเปลี่ยนความหมายของ URI ได้เนื่องจากการตีความสตริงการสืบค้นขึ้นอยู่กับเซิร์ฟเวอร์ หากคุณกำลังสร้างapplication/x-www-form-urlencodedสตริงข้อความค้นหาก็ใช้ได้ หากคุณกำลังแก้ไข URL ที่ผู้ใช้พิมพ์ / วางไว้:ควรปล่อยให้อยู่คนเดียว
tc.

@tc. คุณพูดถูกถ้าลำไส้ใหญ่ถูกใช้เป็นตัวคั่นทั่วไป (หน้า 12 ของ RFC); อย่างไรก็ตามหากไม่ได้ใช้เป็นตัวคั่นทั่วไปการเข้ารหัสทั้งสองควรแก้ปัญหาเหมือนกัน
Edwin Buck

คุณต้องระวังด้วยเนื่องจาก URL ไม่ใช่ส่วนย่อยของ URI: adamgent.com/post/25161273526/urls-are-not-a-subset-of-uris
Adam Gent

5

Java URLEncoder ในตัวกำลังทำในสิ่งที่ควรจะเป็นและคุณควรใช้มัน

A "+" หรือ "20%" มีทั้งทดแทนที่ถูกต้องสำหรับอักขระช่องว่างใน URL ที่ อย่างใดอย่างหนึ่งจะทำงาน

A ":" ควรเข้ารหัสเนื่องจากเป็นอักขระตัวคั่น กล่าวคือ http: // fooหรือftp: // บาร์ ความจริงที่ว่าเบราว์เซอร์เฉพาะสามารถจัดการได้เมื่อไม่ได้เข้ารหัสไม่ได้ทำให้ถูกต้อง คุณควรเข้ารหัส

ตามแนวทางปฏิบัติที่ดีอย่าลืมใช้วิธีการที่ใช้พารามิเตอร์การเข้ารหัสอักขระ โดยทั่วไปจะใช้ UTF-8 ที่นั่น แต่คุณควรระบุไว้อย่างชัดเจน

URLEncoder.encode(yourUrl, "UTF-8");

5
+เป็นเพียงการแสดงช่องว่างในapplication/x-www-form-urlencoded; ไม่รับประกันว่าจะทำงานได้แม้ว่าจะถูก จำกัด ไว้ที่ HTTP ก็ตาม ในทำนองเดียวกัน:ใช้ได้ในสตริงการสืบค้นและไม่ควรแปลงเป็น%3B; เซิร์ฟเวอร์สามารถเลือกตีความแตกต่างกันได้
tc.

1
วิธีนี้ยังเข้ารหัสทับ URL ทั้งหมดและตัวละครอื่น ๆ ซึ่งเป็นส่วนหนึ่งเช่นhttp://การhttp%3A%2F%2Fที่ไม่ถูกต้อง
การกระ

2
@ToKra คุณไม่ควรเข้ารหัสhttp://ส่วนนี้ วิธีนี้ใช้สำหรับพารามิเตอร์คิวรีและข้อมูลในรูปแบบที่เข้ารหัส อย่างไรก็ตามหากคุณต้องการส่ง URL ของเว็บไซต์อื่นเป็นพารามิเตอร์การค้นหาดังนั้นคุณจึงต้องการเข้ารหัสเพื่อหลีกเลี่ยงความสับสนในตัวแยกวิเคราะห์ URL
beldaz

@tc อ่านของฉันw3.org/TR/html4/interact/forms.html#h-17.13.3.3คือข้อมูลรูปแบบได้รับทั้งหมดจะถูกเข้ารหัสเป็นapplication/x-www-form-urlencodedประเภทของเนื้อหา นั่นหมายความว่าต้องใช้งานได้กับ HTTP หรือไม่?
beldaz

0

หากคุณมีปัญหาเฉพาะพื้นที่ใน url ฉันใช้โค้ดด้านล่างและทำงานได้ดี

String url;
URL myUrl = new URL(url.replace(" ","%20"));

ตัวอย่าง: url คือ

www.xyz.com?para=hello ครับ

ผลลัพธ์ของ muUrl คือ

www.xyz.com?para=hello%20sir


0
String param="2019-07-18 19:29:37";
param="%27"+param.trim().replace(" ", "%20")+"%27";

ฉันสังเกตว่าในกรณีของ Datetime (Timestamp) URLEncoder.encode(param,"UTF-8")ไม่ทำงาน

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