能否在XMLHTTPRequest中使用摘要认证(Digest-Authentication)?

8
我有一个简单的问题:能否在XMLHTTPRequest中使用摘要认证(Digest-Authentication)?
如果答案是否定的,那么技术上的原因是什么?如果可以使用摘要认证,该如何实现呢?
谷歌目前没有好的答案,非常感谢您的帮助。
编辑:
感谢回答。在收到nonce后将标头修改为匹配摘要认证方案似乎是一种解决方案。
但我真正想知道的是能否将当前调用:
xmlhttp.open("GET", url, false, username, password);
更改为像这样的调用:
xmlhttp.open("GET", url, false, username, password, "DIGEST");
这也是我最初问题的一部分:为什么open方法不提供进行摘要请求的选项?
也许有js库可以推荐,可以让我这样做 - 您可以想象我真的不想将一个简单的xmlhttp.open更改为多个请求并首先获取nonce。

你目前尝试了什么?如果你的服务器页面需要摘要认证(对未经身份验证的请求返回401),并且你将用户名和密码传递到你的XHR open()调用中,一切都应该正常工作。 - EricLaw
你做完了吗?我会非常感激一些代码。谢谢! - vrunoa
6个回答

9
你没问题的。只需按照规范中你感兴趣的部分进行操作 ;)
https://www.rfc-editor.org/rfc/rfc2617
这是你开始编写认证库所缺少的全部内容。
http://pajhome.org.uk/crypt/md5/
在客户端上。

预交换用户名和密码
嗨,我想要验证 ---->服务器
好的,这里有一个nonce/salt ----> 客户端
这是我的用户名密码时间戳和salt的md5哈希值 -----> 服务器
我刚刚以与您同样的方式混合了您的密码和用户名,并且它们是相同的 ----->客户端
这就是基本原理。

我忘记了你需要在哈希总和中包含所请求资源的URI!
当然,你在向服务器请求资源时都要这样做,这样截取哈希值的人只能查看你请求的内容,而不能请求任何其他资源。这种方法并不保护数据,只保护访问。


我不同意。任何人都可以向服务器请求一个随机数。你如何安全地将其传输到客户端? - Chielus
5
目的是为了防止从md5中猜测密码并使每个验证尝试都非常独特,这样别人就无法在中间进行哈希操作,并在另一个时间重新验证。实际上,他们在OAuth中使用nonce。我知道你在想仍然完全不安全,但这种类型的身份验证只是为了保护您的用户名和密码,非常基本。 - Tegra Detra
1
我想补充一下,这种摘要方法需要服务器以明文形式知道密码。为了更安全的方法,请参阅RFC8146。 - Maxi Wu

6

这是最佳答案。指向某人的帖子,该帖子完成了所有工作并提供了完整的源代码(测试非常简单)。 - Clint Eastwood
是的,除了链接现在已经失效,答案也没有用了。 - Lazar Ljubenović

2
我已经编写了完整的流程,只要使用MD5的外部库(我使用Crypto-js),这并不难。
你可能遇到的最大问题是,在第一次服务器401回复时,任何最常用的浏览器都会打开一个对话框来获取你的凭据。据我所见,没有简单的方法可以规避这个问题:如何抑制浏览器的身份验证对话框? 为了解决这个问题,我修改了我从C# CodePlex项目编写的Web服务器。在第一次请求时,客户端传递一个“警告”标头,表示“不要引发401”。服务器创建挑战并用自定义的、非401 HttpException(我目前使用406,它在HTTP中表示“不可接受”)发送回来。客户端创建哈希并将其发送回来。
如果有人感兴趣,我可以发布一些代码片段,这是一个有点老的问题。

当Safari通过XHR接收到401时,似乎并不是这样。 - wprl
“this”是什么意思?“this”=“浏览器也为XHR 401打开对话框”吗?如果是这样的话,就不需要使用警告头技巧了。广泛兼容的解决方案仍需要一个变通方法。 - malber

0

最好的方法是使用SSL。我认为没有其他安全的解决方案存在(如果我错了,请纠正我)


1
摘要比基本认证+SSL更安全!请查看RFC 2617中有关安全性的部分。 - wprl
1
没有SSL,中间人攻击者(例如敌对或被攻陷的代理;比如在公共WiFi接入点)可以向HTML注入任意JavaScript(或仅链接)。这样,攻击者的请求将源自用户的浏览器,因此服务器将没有任何机会告诉这些请求不是来自用户。攻击者甚至不需要弄清密码。 - robert4

0

你真的不应该关心网站使用哪种身份验证方法,只要你的浏览器支持它就可以了。

如果你指定用户名和密码来打开方法,并且不要搞乱授权头,XMLHttpRequest.send() 将首先尝试发送未经身份验证的请求,接收带有 WWW-Authenticate 头的 401 响应,并重试请求,根据网站请求的授权方法提供名称和密码。

(虽然在这个两阶段过程中可能会触发一些额外的事件处理程序)。


0
为了避免默认的浏览器身份验证对话框,您只需将WWW-Authenticate设置为Digest/YourString(例如您的领域)。这都在第一个响应中,不是很悲惨。我的自定义代码昨天还完美地工作,现在我正在尝试调试突然发生的奇怪问题,仍在努力理解中。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接