ฉันควรใช้การเข้ารหัสอะไรสำหรับ HTTP Basic Authentication


87

RFC2617 ระบุว่าจะเข้ารหัสชื่อผู้ใช้และรหัสผ่านเป็น base64 แต่ไม่ได้บอกว่าจะใช้การเข้ารหัสอักขระใดเมื่อสร้างอ็อกเต็ตสำหรับอินพุตในอัลกอริทึม base64

ฉันควรถือว่า US-ASCII หรือ UTF8? หรือมีคนตัดสินคำถามนี้ไปแล้วบ้าง?


คำตอบ:


74

ข้อมูลจำเพาะดั้งเดิม - RFC 2617

RFC 2617สามารถอ่านได้ว่า "ISO-8859-1" หรือ "ไม่ได้กำหนด" ทางเลือกของคุณ. เป็นที่ทราบกันดีว่าเซิร์ฟเวอร์จำนวนมากใช้ ISO-8859-1 (ชอบหรือไม่) และจะล้มเหลวเมื่อคุณส่งอย่างอื่น ดังนั้นทางเลือกเดียวที่ปลอดภัยคือการยึดติดกับ ASCII

สำหรับข้อมูลเพิ่มเติมและข้อเสนอในการแก้ไขสถานการณ์โปรดดูแบบร่าง"An Encoding Parameter for HTTP Basic Authentication" (ซึ่งเป็นพื้นฐานสำหรับ RFC 7617)

ใหม่ - RFC 7617

ตั้งแต่ปี 2015 มีRFC 7617ซึ่งล้าสมัย RFC 2617 ตรงกันข้ามกับ RFC รุ่นเก่า RFC ใหม่กำหนดการเข้ารหัสอักขระอย่างชัดเจนเพื่อใช้สำหรับชื่อผู้ใช้และรหัสผ่าน

  • การเข้ารหัสเริ่มต้นยังไม่ได้กำหนด จำเป็นต้องเข้ากันได้กับ US-ASCII เท่านั้น (หมายถึงแมป ASCII ไบต์กับไบต์ ASCII เช่นเดียวกับ UTF-8)
  • เซิร์ฟเวอร์สามารถเลือกที่จะส่งพารามิเตอร์การตรวจสอบความถูกต้องเพิ่มเติมcharset="UTF-8"ในการท้าทายเช่นนี้
    WWW-Authenticate: Basic realm="myChosenRealm", charset="UTF-8"
    ซึ่งเป็นการประกาศว่าเซิร์ฟเวอร์จะยอมรับอักขระที่ไม่ใช่ ASCII ในชื่อผู้ใช้ / รหัสผ่านและคาดว่าจะเข้ารหัสเป็น UTF-8 (โดยเฉพาะ Normalization Form C) . โปรดทราบว่าอนุญาตเฉพาะ UTF-8 เท่านั้น

เวอร์ชันสมบูรณ์:

อ่านข้อมูลจำเพาะ หากมีรายละเอียดเพิ่มเติมเช่นขั้นตอนการเข้ารหัสที่แน่นอนและรายการจุดรหัส Unicode ที่ควรได้รับการสนับสนุน

รองรับเบราว์เซอร์

ในปี 2018 เบราว์เซอร์สมัยใหม่มักจะใช้ค่าเริ่มต้นเป็น UTF-8 หากผู้ใช้ป้อนอักขระที่ไม่ใช่ ASCII สำหรับชื่อผู้ใช้หรือรหัสผ่าน (แม้ว่าเซิร์ฟเวอร์จะไม่ใช้charsetพารามิเตอร์ก็ตาม)

  • ดูเหมือนว่า Chrome จะใช้ UTF-8
  • Internet Explorer ไม่ใช้ UTF-8 ( ปัญหา # 11879588 )
  • Firefox กำลังทดลองกับการเปลี่ยนแปลงที่วางแผนไว้สำหรับ v59 ( ข้อบกพร่อง 1419658 )

อาณาจักร

ดินแดนพารามิเตอร์ยังคงสนับสนุนเฉพาะอักขระ ASCII แม้ใน RFC 7617


ขอบคุณ Julian ฉันได้พบกับข้อเสนอนั้น แต่ดูเหมือนว่าจะหมดอายุแล้วและไม่ได้ไปไหนต่อ เสียดาย :-(.
Dobes Vandermeer

1
คำตอบของคุณต้องดีที่สุด ฉันสามารถถอดความเป็น ASCII ได้อย่างแน่นอนอาจเป็น ISO-8859-1 หากคุณโชคดี
Dobes Vandermeer

ดูเหมือนว่าข้อเสนอ 04 เวอร์ชันล่าสุด (ซึ่งบังเอิญดูเหมือนจะเผยแพร่ในวันนี้) จะหมดอายุในวันที่ 1 สิงหาคม 2555
Michiel van Oosterhout

คำตอบนั้นล้าสมัยเนื่องจากไม่ได้กล่าวถึง RFC 7617 ฉันแก้ไขเพื่อรวมสิ่งนี้ Julian: หวังว่าคุณจะไม่รังเกียจ
sleske

อ๊ะ - ฉันเพิ่งรู้ว่าคุณเป็นคนเขียน RFC 7617 ตอนนี้ฉันหวังว่าฉันจะไม่แก้ไขบางอย่างผิด
sleske

41

คำตอบสั้น ๆ : iso-8859-1 เว้นแต่ใช้คำที่เข้ารหัสตาม RFC2047 (MIME)

คำอธิบายอีกต่อไป:

RFC2617 ส่วนที่ 2 (การพิสูจน์ตัวตน HTTP) กำหนดข้อมูลรับรองพื้นฐาน :

basic-credentials = base64-user-pass
base64-user-pass  = <base64 encoding of user-pass, 
                     except not limited to 76 char/line>
user-pass         = userid ":" password
userid            = *<TEXT excluding ":">
password          = *TEXT

ไม่ควรอ่านข้อมูลจำเพาะโดยไม่อ้างถึง RFC2616 (HTTP 1.1) สำหรับคำจำกัดความใน BNF (เช่นเดียวกับด้านบน):

ข้อกำหนดนี้เป็นสหายกับ HTTP / 1.1 สเปค2 ใช้ส่วนเสริม BNF ส่วน 2.1 ของเอกสารนั้นและอาศัยทั้งที่ไม่ใช่เทอร์มินัลที่กำหนดไว้ในเอกสารนั้นและด้านอื่น ๆ ของข้อกำหนด HTTP / 1.1

RFC2616 ส่วน 2.1กำหนดTEXT (เน้นของฉัน):

กฎ TEXT ใช้สำหรับเนื้อหาฟิลด์อธิบายและค่าที่ไม่ได้ตั้งใจให้ตีความโดยตัวแยกวิเคราะห์ข้อความ คำของ * TEXT อาจมีอักขระจากชุดอักขระอื่นนอกเหนือจาก ISO-8859-1เฉพาะเมื่อเข้ารหัสตามกฎของ RFC 2047

TEXT           = <any OCTET except CTLs, but including LWS>

ดังนั้นจึงเป็น iso-8859-1 อย่างแน่นอนเว้นแต่คุณจะตรวจพบการเข้ารหัสอื่น ๆ ตามกฎ RFC2047 (MIME pt.3 ):

// Username: Mike
// Password T€ST
Mike:=?iso-8859-15?q?T€ST?=

ในกรณีนี้เครื่องหมายยูโรในคำว่าจะได้รับการเข้ารหัสเป็น0xA4ไปตามมาตรฐาน ISO-8859-15 ฉันเข้าใจว่าคุณควรตรวจสอบตัวคั่นคำที่เข้ารหัสเหล่านี้แล้วถอดรหัสคำภายในตามการเข้ารหัสที่ระบุ หากไม่เป็นเช่นนั้นคุณจะคิดว่ารหัสผ่านคือ=?iso-8859-15?q?T¤ST?=(สังเกตว่า0xA4จะถูกถอดรหัส¤เมื่อตีความเป็น iso-8859-1)

นี่คือความเข้าใจของฉันฉันไม่พบการยืนยันที่ชัดเจนมากไปกว่า RFC เหล่านี้ และบางเรื่องก็ดูขัดแย้งกัน ตัวอย่างเช่นหนึ่งใน 4 เป้าหมายที่ระบุไว้ของ RFC2047 (MIME, pt.3) คือการกำหนดใหม่:

รูปแบบของข้อความที่อนุญาตสำหรับ ... ข้อมูลส่วนหัวที่เป็นข้อความในชุดอักขระอื่นที่ไม่ใช่ US-ASCII

แต่แล้ว RFC2616 (HTTP 1.1) กำหนดส่วนหัวโดยใช้กฎ TEXT ซึ่งมีค่าเริ่มต้นเป็น iso-8859-1 หมายความว่าทุกคำในส่วนหัวนี้ควรเป็นคำที่เข้ารหัส (เช่น=?...?=แบบฟอร์ม) หรือไม่?

เกี่ยวข้องด้วยไม่มีเบราว์เซอร์ปัจจุบันทำเช่นนี้ พวกเขาใช้ utf-8 (Chrome, Opera), iso-8859-1 (Safari), หน้ารหัสระบบ (IE) หรืออย่างอื่น (เช่นบิตที่สำคัญที่สุดจาก utf-8 ในกรณีของ Firefox)

แก้ไข: ฉันเพิ่งรู้ว่าคำตอบนี้มองปัญหามากกว่าจากมุมมองฝั่งเซิร์ฟเวอร์


การเข้ารหัส RFC 2047 ใช้ไม่ได้ในกรณีนี้
Julian Reschke

@JulianReschke สเป็คระบุไว้อย่างชัดเจนว่า "เมื่อเข้ารหัสตามกฎของ RFC 2047 เท่านั้น" ฉันเข้าใจว่ากฎใน RFC2047 อาจใช้กับส่วนหัว HTTP ไม่ได้ แต่ข้อมูลจำเพาะค่อนข้างชัดเจนในการอ้างถึง ฉันได้เพิ่มความจริงที่ว่าไม่มีเบราว์เซอร์ใดทำสิ่งนี้ได้จริง
Michiel van Oosterhout

4
ข้อกำหนด HTTPbis จะไม่กล่าวถึง RFC 2047 อีกต่อไป
Julian Reschke

เขียนละเอียดมากขอบคุณ @MichielvanOosterhout!
ToastyMallows

5

RFCs กันในกรอบฤดูใบไม้ผลิที่BasicAuthenticationFilterระดับเริ่มต้นคือUTF-8

เหตุผลสำหรับตัวเลือกนี้ฉันเชื่อว่า UTF-8 สามารถเข้ารหัสอักขระที่เป็นไปได้ทั้งหมดในขณะที่ ISO-8859-1 (หรือ ASCII) ไม่ใช่ การพยายามใช้ชื่อผู้ใช้ / รหัสผ่านกับอักขระที่ระบบไม่รองรับอาจนำไปสู่พฤติกรรมที่ใช้งานไม่ได้หรือความปลอดภัยลดลง (อาจแย่กว่านั้น)


1
การใช้ UTF-8 ไม่ได้ช่วยอะไรถ้าอีกฝ่ายไม่รู้เรื่องนี้ ดังนั้นจะเป็นการดีถ้า Spring framework ใช้พารามิเตอร์ charset ที่อธิบายไว้ใน < greenbytes.de/tech/webdav/rfc7617.html#rfc.section.2.1 >
Julian Reschke

1
@JulianReschke ฉันได้แจ้งให้ทราบถึงวิธีการนำไปใช้ในหนึ่งในกรอบที่พบบ่อยที่สุดและเหตุผลที่เป็นไปได้ อย่ายิงแมสเซนเจอร์!
holmis83

4

หากคุณสนใจว่าเบราว์เซอร์ทำอะไรบ้างเมื่อคุณป้อนอักขระที่ไม่ใช่ ascii ที่พรอมต์การเข้าสู่ระบบฉันเพิ่งลองใช้ Firefox

ดูเหมือนว่าจะแปลงเป็น ISO-8859-1 อย่างเฉื่อยชาโดยใช้ไบต์ที่มีนัยสำคัญน้อยที่สุดของค่ายูนิโคดแต่ละค่าเช่น:

User: 豚 (\u8c5a)
Password: 虎 (\u864e)

มีการเข้ารหัสเช่นเดียวกับ:

User: Z (\u005a)
Password: N (\u004e)

0x5a 0x3a 0x4e base64-> WjpO


1
ใช่นั่นเป็นพฤติกรรมเก่าใน Firefox มีการเปลี่ยนแปลง (ใน V57 ดูเหมือน) และตอนนี้ใช้ UTF-8 แทน
sleske

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