在未经授权的请求后禁止NTLM对话框

时间:2020-03-05 18:43:42  来源:igfitidea点击:

在最近的sharepoint项目中,我实现了一个身份验证Web部件,该部件应替代NTLM身份验证对话框。只要用户提供有效的凭据,它就可以正常工作。每当用户提供无效的凭据时,Internet Explorer中就会弹出NTLM对话框。

我的Javascript代码通过XmlHttpRequest进行身份验证,如下所示:

function Login() {
   var request = GetRequest(); // retrieves XmlHttpRequest
   request.onreadystatechange = function() {
      if (this.status == 401) {     // unauthorized request -> invalid credentials
         // do something to suppress NTLM dialog box...
         // already tried location.reload(); and window.location = <url to authentication form>;
      }
   }
   request.open("GET", "http://myServer", false, "domain\username", "password");
   request.send(null);
}

当用户提供无效的凭据时,我不希望显示NTLM对话框。而是应执行身份验证表单中登录按钮的回发。换句话说,浏览器不应发现我的未授权请求。

有什么办法可以通过Javascript做到这一点?

解决方案

回答

IIRC,当请求流中返回以下内容时,浏览器将弹出身份验证对话框:

  • Http的状态为401
  • WWW-Authenticate标头

我猜想我们需要压制其中一个或者两个。最简单的方法是拥有一个登录方法,该方法将使用Base64用户名和密码(我们使用的是HTTPS,对吗?)并返回200的有效/无效状态。密码通过验证后,即可与XHR一起使用。

回答

马克的评论是正确的; NTLM身份验证提示由401响应代码和作为WWW-Authenticate标头中提供的第一种机制的NTLM的存在触发(请参阅:NTLM身份验证协议)。

我不确定我是否正确理解了问题描述,但是我认为我们正在尝试为SharePoint包装NTLM身份验证,这意味着我们无法控制服务器端身份验证协议,对吗?如果我们无法操纵服务器端以避免在凭据失败时发送401响应,那么我们将无法避免此问题,因为它是(客户端)规范的一部分:

XMLHttpRequest对象

If the UA supports HTTP Authentication [RFC2617] it SHOULD consider requests
  originating from this object to be part of the protection space that includes the
  accessed URIs and send Authorization  headers and handle 401 Unauthorised requests
  appropriately. if authentication fails, UAs should prompt the users for credentials.

因此,该规范实际上要求浏览器在XMLHttpRequest中收到任何401响应时相应地提示用户,就像用户直接访问URL一样。据Mark所言,据我所知,真正避免这种情况的唯一方法是让我们控制服务器端并避免401未经授权的响应。

最后一个想法是,我们可以使用代理来解决此问题,例如在另一台Web服务器上使用单独的服务器端脚本。然后,该脚本接受用户并传递参数并检查身份验证,以便用户的浏览器不是原始HTTP请求的发出者,因此不会收到引起提示的401响应。如果以此方式进行操作,则可以从"代理"脚本中查找失败的脚本,如果失败,则再次提示用户直到成功。在成功的身份验证事件中,我们可以像现在一样简单地获取HTTP请求,因为如果正确指定了凭据,一切都会正常进行。