Server.UrlEncode vs. HttpUtility.UrlEncode


คำตอบ:


133

HttpServerUtility.UrlEncodeจะใช้HttpUtility.UrlEncodeภายใน ไม่มีความแตกต่างเฉพาะ เหตุผลของการมีอยู่Server.UrlEncodeคือความเข้ากันได้กับ ASP คลาสสิก


3
สำหรับสิ่งที่ได้รับการหลบหนี ภายในจะเรียกใช้ฟังก์ชั่นนี้อ้างอิง
Jeff

สำหรับผู้อ่าน: โปรดดูคำตอบของ Joel Muller ด้านล่าง นั่นเป็นวิธีที่มีประสิทธิภาพที่สุดในการเข้ารหัส URL: stackoverflow.com/a/603962/190476
Sudhanshu Mishra

264

ฉันมีอาการปวดหัวอย่างมีนัยสำคัญกับวิธีการเหล่านี้ก่อนหน้านี้ฉันขอแนะนำให้คุณหลีกเลี่ยงการเปลี่ยนแปลงใด ๆUrlEncodeและแทนที่จะใช้Uri.EscapeDataString - อย่างน้อยก็มีพฤติกรรมที่เข้าใจได้

มาดูกัน...

HttpUtility.UrlEncode(" ") == "+" //breaks ASP.NET when used in paths, non-
                                  //standard, undocumented.
Uri.EscapeUriString("a?b=e") == "a?b=e" // makes sense, but rarely what you
                                        // want, since you still need to
                                        // escape special characters yourself

แต่สิ่งที่ฉันชอบส่วนตัวต้องเป็นHttpUtility.UrlPathEncode - สิ่งนี้เข้าใจยากจริงๆ มันเข้ารหัส:

  • "" ==> "% 20"
  • "100% จริง" ==> "100 %% 20true" (ตกลง url ของคุณเสียตอนนี้)
  • "test A.aspx # anchor B" ==> "ทดสอบ% 20A.aspx # anchor% 20B "
  • "test A.aspx? hmm # anchor B" ==> "ทดสอบ% 20A.aspx? hmm #anchor B " ( สังเกตความแตกต่างกับลำดับการหลบหนีก่อนหน้า! )

นอกจากนี้ยังมีเอกสาร MSDN ที่เฉพาะเจาะจงอย่างน่ารัก "เข้ารหัสส่วนเส้นทางของสตริง URL สำหรับการส่ง HTTP ที่เชื่อถือได้จากเว็บเซิร์ฟเวอร์ไปยังไคลเอนต์" - โดยไม่อธิบายว่ามันทำอะไร คุณมีโอกาสน้อยที่จะยิงตัวเองด้วยการเดินเท้าด้วย Uzi ...

ในระยะสั้นติดUri.EscapeDataString


4
และน่าเสียดายที่ยังใช้งานไม่ได้เมื่อทำการร้องขอ HTTP กับบางเว็บเซิร์ฟเวอร์ - Uri.EscapeDataString () ไม่ได้เข้ารหัส "!" หรือ "'" ซึ่งแตกต่างจากวิธีการใช้งานเบราว์เซอร์ส่วนใหญ่ของการหลบหนี () ทำงาน ...
คริสอาร์ดอนเนล

6
! และไม่ควรเข้ารหัสอักขระ 'และ' แต่ถ้าเว็บเซิร์ฟเวอร์ buggy ต้องการสิ่งนี้มันง่ายที่จะแก้ไข หลีกเลี่ยงฟังก์ชั่นหลบหนีของ javascript - เป็นรถบั๊กกี้ (เป็นไปไม่ได้ที่จะไปหนึ่งอัน) ดูxkr.us/articles/javascript/encode-compare - แต่โดยย่อ; คุณสามารถใช้ encodeUriComponent () แทนซึ่งทำหน้าที่คล้ายกับ EscapeDataString - ซึ่งเข้ารหัสและคาดเดาได้และย้อนกลับเข้ารหัสสตริงและไม่เข้ารหัส! และ 'ตัวละคร
Eamon Nerbonne

2
นี้เก่า แต่คำถามถูกกระแทกไปที่หน้าแรกดังนั้น .... ส่วนเส้นทางของสตริง url เป็นส่วนหนึ่งระหว่างโดเมนและ? หรือ # ใน URL
Powerlord

2
@Tim: อาจมีหลาย?คนที่จะบอกว่าจะเข้ารหัสและทำหน้าที่เป็นตัวคั่นที่? สำหรับพื้นที่: ในทั้งสองกรณีพื้นที่อยู่ในแฮชดังนั้นการมีหรือไม่มีส่วนของคิวรีแบบสอบถามจึงไม่สำคัญ และในที่สุดมันก็อภัยไม่ได้เลยที่จะทำให้ Uri เสียหายเช่นเดียวกับในตัวอย่างที่สองที่มี% UrlPathEncodeวิธีการที่ borked ธรรมดาและไม่ควรนำมาใช้
Eamon Nerbonne

1
ฉันคิดว่าคำตอบของฉันที่stackoverflow.com/a/13993486/237091อาจทำให้เกิดแสงสว่างเล็กน้อยเกี่ยวกับการใช้ UrlEncode / UrlPathEncode
Scott Stafford

60

ข้างหน้าอย่างรวดเร็วเกือบ 9 ปีนับตั้งแต่ปีนี้เป็นครั้งแรกที่ถามและในโลกของ .NET หลักและ .NET มาตรฐานที่ดูเหมือนว่าตัวเลือกที่พบมากที่สุดที่เรามีสำหรับ URL ที่เข้ารหัสเป็นWebUtility.UrlEncode (ใต้System.Net) และUri.EscapeDataString ตัดสินโดยคำตอบที่ได้รับความนิยมมากที่สุดที่นี่และที่อื่น ๆUri.EscapeDataStringดูจะดีกว่า แต่มันคืออะไร ฉันทำการวิเคราะห์เพื่อทำความเข้าใจความแตกต่างและนี่คือสิ่งที่ฉันได้รับ:

สำหรับจุดประสงค์ในการเข้ารหัส URL อักขระในหนึ่งใน 3 หมวดหมู่: unreserved (ถูกต้องตามกฎหมายใน URL); สงวนไว้ (ตามกฎหมาย แต่มีความหมายพิเศษดังนั้นคุณอาจต้องการเข้ารหัส) และทุกอย่างอื่น (ต้องเข้ารหัสเสมอ)

ตามRFCตัวละครที่สงวนไว้คือ::/?#[]@!$&'()*+,;=

และตัวละครที่ไม่ได้จองเป็นตัวอักษรและตัวเลข -._~

คำตัดสินของศาล

Uri.EscapeDataStringกำหนดภารกิจไว้อย่างชัดเจน:% - เข้ารหัสอักขระที่สงวนและผิดกฎหมายทั้งหมด WebUtility.UrlEncodeมีความคลุมเครือทั้งในคำจำกัดความและการนำไปใช้ ผิดปกติมันเข้ารหัสอักขระที่สงวนไว้บางตัว แต่ไม่ใช่ตัวอักษรอื่น ๆ (ทำไมเครื่องหมายวงเล็บและไม่ใช่วงเล็บเหลี่ยม) และคนแปลกหน้ายังคงเข้ารหัสที่ไม่ได้จองอย่างไร้เดียงสา~อักขระที่

ดังนั้นฉันเห็นด้วยกับคำแนะนำที่เป็นที่นิยม - ใช้Uri.EscapeDataStringเมื่อเป็นไปได้และเข้าใจตัวละครที่สงวนไว้เช่น/และ?จะได้รับการเข้ารหัส หากคุณต้องการจัดการกับสตริงที่มีขนาดใหญ่โดยเฉพาะอย่างยิ่งกับเนื้อหาที่มีการเข้ารหัส URL คุณจะต้องถอยกลับไปที่WebUtility.UrlEncodeและยอมรับนิสัยใจคอของพวกเขาหรือหลีกเลี่ยงปัญหา


แก้ไข:ฉันได้พยายามที่จะแก้ไขทั้งหมดของนิสัยใจคอดังกล่าวข้างต้นในFlurlผ่านUrl.Encode, Url.EncodeIllegalCharactersและUrl.Decodeวิธีการคง สิ่งเหล่านี้อยู่ในแพ็คเกจหลัก (ซึ่งมีขนาดเล็กและไม่รวมเนื้อหา HTTP ทั้งหมด) หรือไม่ก็สามารถคัดลอกมาจากแหล่งที่มาได้ ฉันยินดีรับความคิดเห็น / ข้อเสนอแนะที่คุณมีต่อสิ่งเหล่านี้


นี่คือรหัสที่ฉันใช้เพื่อค้นหาอักขระที่ถูกเข้ารหัสแตกต่างกัน:

var diffs =
    from i in Enumerable.Range(0, char.MaxValue + 1)
    let c = (char)i
    where !char.IsHighSurrogate(c)
    let diff = new {
        Original = c,
        UrlEncode = WebUtility.UrlEncode(c.ToString()),
        EscapeDataString = Uri.EscapeDataString(c.ToString()),
    }
    where diff.UrlEncode != diff.EscapeDataString
    select diff;

foreach (var diff in diffs)
    Console.WriteLine($"{diff.Original}\t{diff.UrlEncode}\t{diff.EscapeDataString}");

2
มันยอดเยี่ยมมาก!
Jorge Aguirre

1
งานที่ยอดเยี่ยมในการตรวจสอบการแก้ไขปัญหาที่แนะนำในกรอบงาน. net สมัยใหม่
Neowizard

มันควรจะกล่าวว่ามีความแตกต่างบางอย่างระหว่างWebUtilityและHttpUtility WebUtilityใช้ตัวพิมพ์ใหญ่และHttpUtilityใช้ตัวพิมพ์เล็กสำหรับเอนทิตี hexa นอกจากนี้HttpUtilityไม่รวมอยู่ใน. NET Framework "ไคลเอนต์โปรไฟล์" รุ่นย่อยเซ็ตเก่า WebUtilityหาได้จาก. NET Framework 4.0
tibx

28

โปรดทราบว่าคุณไม่ควรใช้วิธีการใดวิธีการหนึ่งต่อไปนี้ ไลบรารี่การเขียนสคริปต์ต่อต้านไซต์ของ Microsoft รวมถึงการแทนที่HttpUtility.UrlEncodeและHttpUtility.HtmlEncodeที่สอดคล้องกับมาตรฐานมากกว่าและปลอดภัยยิ่งขึ้น ในฐานะโบนัสคุณจะได้รับJavaScriptEncodeวิธีการเช่นกัน


หลังจากอ่านเอกสารและคำถามที่พบบ่อยในลิงค์ที่ให้ไว้ฉันเชื่อว่าคำตอบนี้เป็นวิธีที่ดีที่สุดและปลอดภัยที่สุดในการเข้ารหัสข้อมูล! ขอบคุณที่แชร์สิ่งนี้!
Sudhanshu Mishra

ลิงก์ไม่ทำงานอีกต่อไป วิธีการทดแทนคืออะไร?
Edward Brey

@EdwardBrey นี่เป็นเวอร์ชันล่าสุดของ
ไลบรารี่การ

11

Server.UrlEncode () มีไว้เพื่อให้เข้ากันได้ย้อนหลังกับ Classic ASP

Server.UrlEncode(str);

เทียบเท่ากับ:

HttpUtility.UrlEncode(str, Response.ContentEncoding);

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