Tôi nên sử dụng mã hóa nào cho Xác thực cơ bản HTTP?


84

RFC2617 cho biết mã hóa tên người dùng và mật khẩu thành base64 nhưng không cho biết mã hóa ký tự nào sẽ sử dụng khi tạo các octet để nhập vào thuật toán base64.

Tôi nên giả sử US-ASCII hay UTF8? Hay ai đó đã giải quyết câu hỏi này ở đâu đó rồi?


Câu trả lời:


72

Thông số ban đầu - RFC 2617

RFC 2617 có thể được đọc là "ISO-8859-1" hoặc "không xác định". Lựa chọn của bạn. Được biết, nhiều máy chủ sử dụng ISO-8859-1 (dù muốn hay không) và sẽ bị lỗi khi bạn gửi thứ khác. Vì vậy, có lẽ sự lựa chọn an toàn duy nhất là gắn bó với ASCII.

Để biết thêm thông tin và đề xuất để khắc phục tình huống, hãy xem bản thảo "Thông số mã hóa cho xác thực cơ bản HTTP" (đã hình thành cơ sở cho RFC 7617).

Mới - RFC 7617

Kể từ năm 2015, có RFC 7617 , loại bỏ RFC 2617. Ngược lại với RFC cũ, RFC mới xác định rõ ràng mã hóa ký tự được sử dụng cho tên người dùng và mật khẩu.

  • Mã hóa mặc định vẫn chưa được xác định. Chỉ được yêu cầu để tương thích với US-ASCII (có nghĩa là nó ánh xạ các byte ASCII thành các byte ASCII, giống như UTF-8).
  • Máy chủ có thể tùy chọn gửi một tham số xác thực bổ sung charset="UTF-8"trong thử thách của nó, như sau:
    WWW-Authenticate: Basic realm="myChosenRealm", charset="UTF-8"
    Điều này thông báo rằng máy chủ sẽ chấp nhận các ký tự không phải ASCII trong tên người dùng / mật khẩu và nó hy vọng chúng được mã hóa trong UTF-8 (cụ thể là Biểu mẫu chuẩn hóa C) . Lưu ý rằng chỉ UTF-8 mới được phép.

Phiên bản hoàn chỉnh:

Đọc thông số kỹ thuật . Nếu chứa các chi tiết bổ sung, chẳng hạn như quy trình mã hóa chính xác và danh sách mã điểm Unicode cần được hỗ trợ.

Hỗ trợ trình duyệt

Kể từ năm 2018, các trình duyệt hiện đại thường sẽ mặc định là UTF-8 nếu người dùng nhập các ký tự không phải ASCII cho tên người dùng hoặc mật khẩu (ngay cả khi máy chủ không sử dụng charsettham số).

  • Chrome dường như cũng sử dụng UTF-8
  • Internet Explorer không sử dụng UTF-8 (sự cố # 11879588 )
  • Firefox đang thử nghiệm một thay đổi hiện được lên kế hoạch cho v59 ( lỗi 1419658 )

Vương quốc

Các lĩnh vực tham số vẫn chỉ hỗ trợ các ký tự ASCII ngay cả trong RFC 7617.


Cảm ơn Julian. Tôi đã chạy đến đề xuất đó nhưng dường như đã hết hạn và không đi đâu xa hơn. Quá tệ :-(.
Dobes Vandermeer

1
Câu trả lời của bạn phải là tốt nhất. Tôi có thể diễn giải nó là ASCII chắc chắn, có thể là ISO-8859-1 nếu bạn may mắn.
Dobes Vandermeer

Dường như các phiên bản mới nhất 04 của đề xuất (mà tình cờ dường như được công bố ngày nay) hết hiệu lực vào ngày 1 tháng 8, 2012.
Michiel van Oosterhout

Câu trả lời đã lỗi thời, vì nó không đề cập đến RFC 7617. Tôi đã chỉnh sửa để bao gồm điều này. Julian: Mong bạn không phiền.
sleske

Rất tiếc - Tôi vừa nhận ra bạn thực sự là tác giả của RFC 7617. Bây giờ, tôi thực sự hy vọng mình đã không chỉnh sửa sai điều gì đó.
sleske

41

Câu trả lời ngắn gọn: iso-8859-1 trừ khi các từ được mã hóa được sử dụng theo RFC2047 (MIME).

Giải thích dài hơn:

RFC2617, phần 2 (Xác thực HTTP) xác định thông tin đăng nhập cơ bản :

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

Không nên đọc thông số kỹ thuật mà không tham chiếu đến RFC2616 (HTTP 1.1) để biết các định nghĩa trong BNF (như định nghĩa ở trên):

Đặc điểm kỹ thuật này là bạn đồng hành với đặc điểm kỹ thuật HTTP / 1.1 2 . Nó sử dụng BNF tăng cường phần 2.1 của tài liệu đó và dựa trên cả các thiết bị đầu cuối không được xác định trong tài liệu đó và các khía cạnh khác của đặc tả HTTP / 1.1.

RFC2616, phần 2.1 định nghĩa TEXT (mỏ nhấn mạnh):

Quy tắc TEXT chỉ được sử dụng cho nội dung trường mô tả và các giá trị không được trình phân tích cú pháp thông báo giải thích. Các từ của * TEXT CÓ THỂ chứa các ký tự từ các bộ ký tự không phải ISO-8859-1 chỉ khi được mã hóa theo các quy tắc của RFC 2047.

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

Vì vậy, nó chắc chắn là iso-8859-1 trừ khi bạn phát hiện một số mã hóa khác theo quy tắc RFC2047 (MIME pt. 3):

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

Trong trường hợp này, ký hiệu euro trong từ sẽ được mã hóa 0xA4theo iso-8859-15 . Tôi hiểu rằng bạn nên kiểm tra các dấu phân cách từ được mã hóa này, và sau đó giải mã các từ bên trong dựa trên mã hóa được chỉ định. Nếu không, bạn sẽ nghĩ là mật khẩu =?iso-8859-15?q?T¤ST?=(lưu ý rằng mật khẩu 0xA4sẽ được giải mã ¤khi được hiểu là iso-8859-1).

Đây là sự hiểu biết của tôi, tôi không thể tìm thấy xác nhận rõ ràng hơn những RFC này. Và một số có vẻ mâu thuẫn. Ví dụ: một trong 4 mục tiêu đã nêu của RFC2047 (MIME, pt. 3) là xác định lại:

định dạng thông báo để cho phép ... thông tin tiêu đề dạng văn bản trong các bộ ký tự khác với US-ASCII.

Nhưng sau đó RFC2616 (HTTP 1.1) xác định tiêu đề bằng quy tắc TEXT được mặc định là iso-8859-1. Điều đó có nghĩa là mọi từ trong tiêu đề này phải là một từ được mã hóa (tức là =?...?=biểu mẫu)?

Cũng có liên quan, không có trình duyệt hiện tại nào làm được điều này. Họ sử dụng utf-8 (Chrome, Opera), iso-8859-1 (Safari), trang mã hệ thống (IE) hoặc thứ gì đó khác (chỉ như bit quan trọng nhất từ ​​utf-8 trong trường hợp của Firefox).

Chỉnh sửa: Tôi vừa nhận ra câu trả lời này xem xét vấn đề nhiều hơn từ góc độ phía máy chủ.


Mã hóa RFC 2047 không áp dụng trong trường hợp này.
Julian Reschke,

@JulianReschke Chà, thông số ghi rõ "chỉ khi được mã hóa theo các quy tắc của RFC 2047". Tôi hiểu các quy tắc trong RFC2047 có thể không áp dụng được cho các tiêu đề HTTP, nhưng thông số kỹ thuật khá rõ ràng khi đề cập đến nó. Tôi đã nói thêm rằng không có trình duyệt nào thực sự làm được điều này.
Michiel van Oosterhout

4
thông số kỹ thuật HTTPbis sẽ không đề cập đến RFC 2047 nữa.
Julian Reschke,

Bài viết rất chi tiết, cảm ơn @MichielvanOosterhout!
ToastyMallows

5

RFCs sang một bên, trong khuôn khổ Spring , BasicAuthenticationFilterlớp, mặc định là UTF-8 .

Lý do cho sự lựa chọn này, tôi tin rằng UTF-8 có khả năng mã hóa tất cả các ký tự có thể có, trong khi ISO-8859-1 (hoặc ASCII) thì không. Việc cố gắng sử dụng tên người dùng / mật khẩu với các ký tự không được hỗ trợ trong hệ thống có thể dẫn đến hành vi bị hỏng hoặc (có thể tệ hơn) bảo mật bị suy giảm.


1
Chà, việc sử dụng UTF-8 sẽ không hữu ích nếu phía bên kia không biết về nó. Vì vậy, nó sẽ là tốt nếu khuôn khổ mùa xuân thực hiện các tham số charset được mô tả trong < greenbytes.de/tech/webdav/rfc7617.html#rfc.section.2.1 >
Julian Reschke

1
@JulianReschke Tôi đã thông báo về cách nó được triển khai trong một trong những khuôn khổ phổ biến nhất và một lý do có thể cho nó. Đừng bắn người đưa tin!
holmis83 14/02/17

4

Nếu bạn quan tâm đến những gì trình duyệt làm khi bạn nhập các ký tự không phải ascii tại lời nhắc đăng nhập, tôi vừa thử với Firefox.

Nó dường như chuyển đổi everithing sang ISO-8859-1 một cách lười biếng bằng cách lấy byte ít quan trọng nhất của mỗi giá trị unicode, ví dụ:

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

Được mã hóa giống như:

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

0x5a 0x3a 0x4e base64-> WjpO


1
Vâng, đó là hành vi cũ trong Firefox. Nó đã được thay đổi (có vẻ như trong V57) và bây giờ sử dụng UTF-8 để thay thế.
sleske

1
V59, không phải V57. Hiện đang trong giai đoạn thử nghiệm beta.
Julian Reschke
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.