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?
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:
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).
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.
charset="UTF-8"
trong thử thách của nó, như sau: WWW-Authenticate: Basic realm="myChosenRealm", charset="UTF-8"
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ợ.
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 charset
tham số).
Các lĩnh vực tham số vẫn chỉ hỗ trợ các ký tự ASCII ngay cả trong RFC 7617.
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 0xA4
theo 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 0xA4
sẽ đượ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ủ.
RFCs sang một bên, trong khuôn khổ Spring , BasicAuthenticationFilter
lớ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.
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