在HTTP Basic Auth用户名中损坏了UTF-8字符

我正在尝试使用Ruby on Rails构建Web服务。 用户通过HTTP Basic Auth进行身份validation。 我想在用户名和密码中允许任何有效的UTF-8字符。

问题是浏览器在将它们发送到我的服务之前会破坏Basic Auth凭证中的字符。 为了测试,我使用’カタカナカタカナカタカナカタカナカタカナカタカナカタカナカタカナカタカナカタカナ’作为我的用户名(不知道它是什么意思 – AFAIK它是我们的QA家伙想出的一些随机字符 – 请原谅我,如果它是某种方式令人反感)。

如果我把它看作一个字符串,并做username.unpack(“H *”)将其转换为hex,我得到:“3e28ba3e28fb3e28ba3e38a83e28ba3e28fb3e28ba3e38a83e28ba3e28fb3e28ba3e38a83e28ba3e28fb3e28ba3e38a83e28ba3e28fb3e28ba3e38a83e28ba3e28fb3e28ba3e38a83e28ba3e28fb3e28ba3e38a83e28ba3e28fb3e28ba3e38a8”这似乎是对适合32个汉字字符(3个字节元/ 6个hex数字)。

如果我使用通过HTTP Basic auth进入的用户名执行相同的操作,我会得到:’bafbbaacbafbbaacbafbbaacbafbbaacbafbbaacbafbbaacbafbbaacbafbbaac’。 它显然要短得多。 使用Firefox Live HTTP Headers插件,这是发送的实际标头:

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

看起来像’bafbba …’字符串,交换了高低字节(至少当我将其粘贴到Emacs中时,基本64解码,然后切换到hexl模式)。 这可能是用户名的UTF16表示,但我没有任何东西可以将它显示为除了胡言乱语之外的任何东西。

Rails将内容类型标头设置为UTF-8,因此浏览器应该以该编码发送。 我获得了表单提交的正确数据。

问题出现在Firefox 3.0.8和IE 7中。

那么…是否有一些神奇的function让网络浏览器通过HTTP Basic Auth发送UTF-8字符? 我在接收端处理错误了吗? HTTP Basic Auth是否不适用于非ASCII字符?

我想在用户名和密码中允许任何有效的UTF-8字符。

放弃所有的希望。 基本身份validation和Unicode不混合。

如何将非ASCII字符编码为基本认证用户名:base64ing之前的密码令牌没有标准(*)。 因此,每个浏览器都会执

  • Opera使用UTF-8;
  • IE使用系统的默认代码页(除了它永远不会是UTF-8之外你无法知道),并使用Windows来猜测一个看起来有点像的随机字符,然后默默地修改不符合它的字符。一个你想要的或者可能不是’秘方;
  • Mozilla只使用字符代码点的低字节,它具有编码到ISO-8859-1的效果,并且不可挽回地破坏非8859-1字符… 除了在执行XMLHttpRequests时,在这种情况下它使用UTF-8;
  • Safari和Chrome编码为ISO-8859-1,并且在使用非8859-1字符时根本无法发送授权标头。

*:有些人解释标准说:

  • 它应该始终是ISO-8859-1,因为它是包含直接包含在头文件中的原始8位字符的默认编码;
  • 它应该以某种方式使用RFC2047规则进行编码。

但是这些提议都没有包含在base64编码的auth令牌中,并且HTTP规范中的RFC2047引用实际上根本不起作用,因为’primefaces上下文明确禁止它可能使用的所有地方“RFC2047本身的规则,即使HTTP标头尊重RFC822系列的规则和扩展,它们也没有。

总结:呃。 除了Opera之外,在标准或浏览器中修复这一点几乎没有希望。 这只是推动人们远离HTTP基本身份validation的另一个因素,有利于非标准和不易访问的基于cookie的身份validation方案。 真惭愧。

这是一个众所周知的缺点,即基本身份validation不支持非ISO-8859-1字符。

已知一些UA使用UTF-8(Opera会想到),但也没有互操作性。

据我所知,除了定义一个处理所有Unicode的新身份validation方案之外,没有办法解决这个问题。 并部署它。

HTTP摘要身份validation也不是解决此问题的方法。 它遇到了同样的问题,即客户端无法告诉服务器它正在使用什么字符集,并且服务器无法正确地假设客户端使用了什么。

您是否使用curl等测试来确保它不是Firefox问题? HTTP Auth RFC在ASCII与非ASCII上是静默的,但它确实表示在标题中传递的值是用冒号分隔的用户名和密码,我在Firefox报告的字符串中找不到冒号发送。

如果您要编写Windows 8.1,请注意HttpCredentialsHeaderValue文档中的HttpCredentialsHeaderValue是(错误地)使用UTF-16编码。 合理的解决方法是切换到UTF-8(因为CryptographicBuffer.ConvertStringToBinary不支持ISO-8859-1)。

请参阅http://msdn.microsoft.com/en-us/library/windows/apps/windows.web.http.headers.httpcredentialsheadervalue.aspx 。

我可能是一个完全无知的人,但是当我在ajax调用中发送UTF8字符串作为标题时,我找到了这个问题。

我可以通过在发送它之前在Base64中编码字符串来解决我的问题。 这意味着您可以使用一些简单的JS在提交之前将表单转换为base64,这样就可以将其转换回服务器端。

这个简单的工具允许我将utf8字符串作为简单的ASCII发送。 我发现感谢这句简单的句子:

base64(此编码旨在使二进制数据在通过非8位干净的传输层传输时继续存在)。 http://www.webtoolkit.info/javascript-base64.html

我希望这会有所帮助。 试着回馈一下社区吧!