2009-03-31 38 views
27

Tôi đang cố gắng xây dựng một dịch vụ web bằng Ruby on Rails. Người dùng tự xác thực thông qua Xác thực cơ bản HTTP. Tôi muốn cho phép bất kỳ ký tự UTF-8 hợp lệ nào trong tên người dùng và mật khẩu.Ký tự UTF-8 bị xáo trộn trong tên người dùng Auth HTTP cơ bản

Vấn đề là trình duyệt mang các ký tự mangling trong thông tin xác thực cơ bản trước khi gửi chúng đến dịch vụ của tôi. Để kiểm tra, tôi sử dụng tên người dùng của mình (không biết ý nghĩa của nó là gì - AFAIK là một số nhân vật ngẫu nhiên mà nhân viên QA của chúng tôi đã đưa ra - hãy tha thứ cho tôi nếu nó bằng cách nào đó xúc phạm).

Nếu tôi coi đó là một chuỗi và làm username.unpack ("h *") để chuyển nó sang hex, tôi nhận được: '3e28ba3e28fb3e28ba3e38a83e28ba3e28fb3e28ba3e38a83e28ba3e28fb3e28ba3e38a83e28ba3e28fb3e28ba3e38a83e28ba3e28fb3e28ba3e38a83e28ba3e28fb3e28ba3e38a83e28ba3e28fb3e28ba3e38a83e28ba3e28fb3e28ba3e38a8' Đó có vẻ đúng cho 32 kanji ký tự (3 byte/6 hex chữ số cho mỗi).

Nếu tôi làm như vậy với tên người dùng truy cập qua xác thực HTTP cơ bản, tôi nhận được: 'bafbbaacbafbbaacbafbbaacbafbbaacbafbbaacbafbbaacbafbbaacbafbbaac'. Nó rõ ràng là ngắn hơn nhiều. Sử dụng các plugin trình duyệt Firefox Live HTTP Headers, đây là tiêu đề thực tế mà đang được gửi:

Authorization: Basic q7+ryqu/q8qrv6vKq7+ryqu/q8qrv6vKq7+ryqu/q8o6q7+ryqu/q8qrv6vKq7+ryqu/q8qrv6vKq7+ryqu/q8o= 

Trông giống như đó là bafbba ... 'chuỗi, với Nibbles cao và thấp hoán đổi (ít nhất là khi tôi dán nó vào Emacs, cơ sở 64 giải mã, sau đó chuyển sang chế độ hexl). Đó có thể là một đại diện UTF16 của tên người dùng, nhưng tôi đã không nhận được bất cứ điều gì để hiển thị nó như bất cứ điều gì nhưng vô nghĩa.

Đường ray đang đặt tiêu đề loại nội dung thành UTF-8, do đó trình duyệt sẽ gửi trong mã hóa đó. Tôi nhận được dữ liệu chính xác để gửi biểu mẫu.

Vấn đề xảy ra trong cả Firefox 3.0.8 và IE 7.

... Vì vậy, có một số bộ lọc tuyệt vời để nhận các trình duyệt web để gửi UTF-8 ký tự thông qua HTTP Basic Auth? Tôi có xử lý mọi thứ sai trên đầu nhận không? Có phải HTTP Basic Auth không hoạt động với các ký tự không phải ASCII?

+3

Thông tin bên lề: "Ký tự ngẫu nhiên" không gây khó chịu. Họ là người Nhật, và nói "katakana" (8 lần) trong kịch bản Katakana http://en.wikipedia.org/wiki/Katakana thường được sử dụng để đánh vần các từ và âm thanh không phải tiếng Nhật. (Đó là lẻ, bởi vì "katakana" * là * một từ tiếng Nhật vì vậy thường không phải là viết tắt trong katakana :-) – bignose

+0

Phụ lục đố: Tôi đã thấy nó được viết bằng katakana rất nhiều. Ban đầu tôi đặt nó xuống cho những người cố gắng để được thơ mộng, nhưng tôi chỉ nhìn nó trong Jisho và nó nói rằng nó "thường được viết bằng kana". – Trejkaz

Trả lời

52

Tôi muốn cho phép bất kỳ ký tự UTF-8 hợp lệ nào trong tên người dùng và mật khẩu.

Bỏ qua tất cả hy vọng. Xác thực cơ bản và Unicode không trộn lẫn.

Không có tiêu chuẩn (*) để biết cách mã hóa các ký tự không phải ASCII thành tên người dùng xác thực cơ bản: mã thông báo mật khẩu trước khi căn cứ vào nó.Do đó, mọi trình duyệt đều thực hiện điều gì đó khác nhau:

  • Opera sử dụng UTF-8;
  • IE sử dụng bảng mã mặc định của hệ thống (bạn không biết cách nào khác ngoài UTF-8) và âm thầm mang các ký tự không phù hợp với Windows bằng cách đoán một ký tự ngẫu nhiên trông giống như giống như cái bạn muốn hoặc có thể không phải là 'công thức bí mật;
  • Mozilla chỉ sử dụng byte dưới của các điểm mã ký tự, có hiệu lực mã hóa theo ISO-8859-1 và xâu chuỗi các ký tự không phải là 8859-1 một cách không thể tin được ... trừ khi thực hiện XMLHttpRequests. UTF-8;
  • Safari và Chrome mã hóa thành ISO-8859-1 và không gửi tiêu đề cấp quyền hoàn toàn khi sử dụng ký tự không phải là 8859-1.

*: một số người giải thích các tiêu chuẩn để nói rằng một trong hai:

  • nó phải luôn ISO-8859-1, do đó là mã hóa mặc định cho nhân vật bao gồm 8-bit liệu trực tiếp bao gồm trong tiêu đề;
  • phải được mã hóa bằng quy tắc RFC2047, bằng cách nào đó.

Nhưng không có đề xuất nào trong số này được đưa vào mã thông báo xác thực base64 và tham chiếu RFC2047 trong thông số HTTP thực sự không hoạt động vì tất cả các địa điểm có thể được sử dụng rõ ràng không được chấp nhận bởi các quy tắc 'bối cảnh nguyên tử' của chính RFC2047, ngay cả khi tiêu đề HTTP đã tôn trọng các quy tắc và phần mở rộng của họ RFC822 mà chúng không có.

Tóm lại: ugh. Có rất ít hy vọng rằng điều này đã từng được khắc phục trong tiêu chuẩn hoặc trong các trình duyệt khác ngoài Opera. Đó chỉ là một yếu tố nữa thúc đẩy mọi người tránh khỏi Xác thực cơ bản HTTP để ủng hộ các chương trình xác thực dựa trên cookie không chuẩn và ít truy cập được. Xấu hổ thực sự.

+1

Tôi tình cờ không đồng ý rằng Opera làm điều đó bằng cách nào đó đúng. Bạn không thể thay đổi mã hóa đơn phương. –

+0

Không quá nhiều ‘đúng’ như “những gì OP muốn làm”. Mặc dù không có lựa chọn thay thế nào là ‘đúng’, UTF-8 ít nhất cũng tốt như bất kỳ lựa chọn nào khác có thể. – bobince

+0

Ít nhất UTF-8 sẽ không mangle một số ký tự :) Cảm ơn rất nhiều cho câu trả lời này (nó mở rộng trên Julian's - cả hai đều trả lời câu hỏi độc đáo). Tôi đã làm rất nhiều Googling và không thể tìm thấy một cuộc thảo luận vững chắc về điều này. Đã đến lúc thay đổi thông số kỹ thuật của tôi. – edebill

0

Bạn đã thử nghiệm bằng cách sử dụng một cái gì đó như curl để đảm bảo đó không phải là vấn đề với Firefox? HTTP Auth RFC im lặng trên ASCII và không phải ASCII, nhưng nó nói giá trị được truyền trong tiêu đề là tên người dùng và mật khẩu được phân tách bằng dấu hai chấm và tôi không thể tìm thấy dấu hai chấm trong chuỗi mà Firefox đang gửi báo cáo.

+0

Có một dấu hai chấm ở đó, khi bạn giải mã64. Nó kết thúc lên là 32 ký tự 16 bit (ít nhất là Emacs nghĩ rằng chúng là ký tự), dấu hai chấm, sau đó cùng một ký tự 16 bit (tôi đã sử dụng cùng một chuỗi cho mật khẩu). Tôi đã thử nó với IE và có cùng một thứ, vì vậy nó không chỉ là một điều Firefox. – edebill

+0

Tôi chỉ sử dụng một số tiện ích bảng điều khiển OS X để thực hiện chuyển đổi, nhưng chắc chắn không tìm thấy dấu hai chấm sau khi giải mã base64. Nó chắc hẳn đã cố gắng sử dụng MacRoman hay gì đó. –

5

Đó là một thiếu sót được biết đến mà xác thực cơ bản không cung cấp hỗ trợ cho các ký tự không phải ISO-8859-1.

Một số UA được biết là sử dụng UTF-8 thay vào đó (Opera xuất hiện trong đầu), nhưng không có khả năng tương tác cho điều đó.

Theo như tôi có thể nói, không có cách nào để sửa lỗi này, ngoại trừ bằng cách xác định lược đồ xác thực mới xử lý tất cả Unicode. Và làm cho nó được triển khai.

3

Xác thực thông báo HTTP cũng không có giải pháp cho vấn đề này. Nó bị cùng một vấn đề của khách hàng là không thể nói cho máy chủ những gì bộ ký tự nó đang sử dụng và máy chủ không thể giả định chính xác những gì khách hàng sử dụng.

-1

Tôi có thể là một người không biết gì, nhưng tôi đã đến bài viết này trong khi tìm kiếm một vấn đề trong khi gửi một chuỗi UTF8 như là một tiêu đề bên trong một cuộc gọi ajax.

Tôi có thể giải quyết vấn đề của mình bằng cách mã hóa trong Base64 chuỗi ngay trước khi gửi. Điều đó có nghĩa rằng bạn có thể với một số JS đơn giản chuyển đổi các hình thức để base64 ngay trước khi submittting và theo cách đó nó có thể được conevrted trở lại ở phía máy chủ.

Công cụ đơn giản này cho phép tôi có các chuỗi utf8 gửi dưới dạng ASCII đơn giản. Tôi thấy rằng nhờ câu đơn giản này:

base64 (mã hóa này được thiết kế để làm cho dữ liệu nhị phân tồn tại truyền qua các lớp vận chuyển không sạch 8 bit). http://www.webtoolkit.info/javascript-base64.html

Tôi hy vọng điều này sẽ giúp bằng cách nào đó. Chỉ cố gắng trả lại một chút cho cộng đồng!

Các vấn đề liên quan