it-swarm.cn

如何禁止浏览器的身份验证对话框?

我的Web应用程序有一个登录页面,通过AJAX调用提交身份验证凭据。如果用户输入正确的用户名和密码,一切都很好,但如果没有,则会发生以下情况:

  1. Web服务器确定虽然请求包含格式良好的Authorization标头,但标头中的凭据无法成功进行身份验证。
  2. Web服务器返回401状态代码,并包含一个或多个WWW-Authenticate标头,列出支持的身份验证类型。
  3. 浏览器检测到对XMLHttpRequest对象的调用的响应是401,响应包括WWW-Authenticate头。然后它会弹出一个身份验证对话框,再次询问用户名和密码。

这一切都很好,直到第3步。我不想弹出对话框,我想要在我的AJAX回调函数中处理401响应。 (例如,通过在登录页面上显示错误消息。)我希望用户重新输入他们的用户名和密码,当然,但我希望他们看到我友好,安心的登录表单,而不是浏览器的丑陋,默认验证对话框。

顺便说一下,我无法控制服务器,所以让它返回自定义状态代码(即401以外的东西)不是一种选择。

有什么办法可以抑制身份验证对话框吗?特别是,我可以在Firefox 2或更高版本中禁止“需要验证”对话框吗?有没有办法在IE 6及更高版本中禁止连接到 [主机] 对话框?


编辑
作者提供的其他信息(9月18日):
我应该补充一点,浏览器的身份验证对话框弹出的真正问题是它给用户提供的信息不足。

用户刚刚通过登录页面上的表单输入了用户名和密码,他认为他已经正确输入了这些用户名和密码,并且他点击了提交按钮或按回车键。他的期望是,他将被带到下一页,或者可能被告知他输入的信息不正确,应该再试一次。但是,他会出现一个意外的对话框。

对话框没有确认他只是输入用户名和密码。它没有明确说明存在问题,他应该再试一次。相反,该对话框向用户显示隐藏信息,如“网站说:' [realm] '。” Where [realm] 是一个只有程序员才会喜欢的简短域名。

Web broswer设计师注意到:如果对话框本身更加用户友好,没有人会问如何抑制身份验证对话框。 whole 我正在做登录表单的原因是我们的产品管理团队正确地认为浏览器的身份验证对话框很糟糕。

73
dgvid

我不认为这是可能的 - 如果您使用浏览器的HTTP客户端实现,它将始终弹出该对话框。想到两个黑客:

  1. 也许Flash以不同的方式处理(我还没有尝试过),所以有一个flash电影使请求可能会有所帮助。

  2. 您可以为您在自己的服务器上访问的服务设置“proxie”,并让它稍微修改一下身份验证标头,以便浏览器无法识别它们。

17
Marijn

我在这里遇到了同样的问题,我公司的后端工程师实现了一种显然被认为是一种好习惯的行为:当一个URL的调用返回401时,如果客户端设置了头X-Requested-With: XMLHttpRequest,则服务器丢弃www-authenticate头在其回应中。

副作用是不显示默认的身份验证弹出窗口。

确保您的API调用X-Requested-With标头设置为XMLHttpRequest。如果是这样,除了根据这种良好做法改变服务器行为之外没有任何事情要做......

45
Antoine Banctel-Chevrel

当满足以下两个条件时,浏览器会弹出登录提示:

  1. HTTP状态为4xx
  2. 响应中存在WWW-Authenticate标头

如果您可以控制HTTP响应,则可以从响应中删除WWW-Authenticate标头,浏览器不会弹出登录对话框。

如果无法控制响应,则可以设置代理以从响应中过滤掉WWW-Authenticate标头。

据我所知(如果我错了,请随意纠正我),一旦浏览器收到WWW-Authenticate标题,就无法阻止登录提示。

14
rustyx

我意识到这个问题及其答案很古老。但是,我最终到了这里。也许其他人也会这样。

如果您有权访问返回401的Web服务的代码。只需更改服务以在此情况下返回403(禁止)而不是401.浏览器不会提示凭据以响应403. 403是未经授权的特定资源的经过身份验证的用户的正确代码。这似乎是OP的情况。

从IETF关于403的文件:

接收不足以获取访问权限的有效凭据的服务器应该使用403(禁止)状态代码进行响应

5
Jim Reineri

在Mozilla中,您可以在创建XMLHttpRequest对象时使用以下脚本实现它:

xmlHttp=new XMLHttpRequest();
xmlHttp.mozBackgroundRequest = true;
xmlHttp.open("GET",URL,true,USERNAME,PASSWORD);
xmlHttp.send(null);

第二行阻止对话框....

4
Yogesh

jan.vdbergh说实话,如果你可以在服务器端更改另一个状态代码的401,浏览器将无法捕获并绘制弹出窗口。另一种解决方案可能是更改另一个自定义标头的WWW-Authenticate标头。我不相信为什么不同的浏览器不能支持它,在几个版本的Firefox中我们可以用mozBackgroundRequest做xhr请求,但在其他浏览器中?在这里,有一个有趣的 链接 在Chromium中有这个问题。

2
Kalamarico

在Mozilla中,将XMLHttpRequest( docs )的mozBackgroundRequest参数设置为true会抑制这些对话框并导致请求完全失败。但是,我不知道跨浏览器支持有多好(包括那些失败请求的错误信息的质量是否在浏览器中非常好。)

2
rakslice

您使用什么服务器技术,是否有用于身份验证的特定产品?

由于浏览器只是在完成它的工作,我相信你必须改变服务器端的东西而不返回401状态代码。这可以使用自定义身份验证表单来完成,只需在身份验证失败时再次返回表单。

2
jan.vdbergh

我对MVC 5和VPN也有同样的问题,每当我们在DMZ之外使用VPN时,我们发现自己必须回答这个浏览器消息。使用.net我只是处理错误的路由

<customErrors defaultRedirect="~/Error"  >
  <error statusCode="401" redirect="~/Index"/>
</customErrors>

到目前为止,它已经起作用,因为家庭控制器下的索引操作验证了用户。如果登录失败,此操作中的视图具有登录控件,我使用该登录控件使用传递到目录服务的LDAP查询来记录用户:

      DirectoryEntry entry = new DirectoryEntry("LDAP://OurDomain");
      DirectorySearcher Dsearch = new DirectorySearcher(entry);
      Dsearch.Filter = "(SAMAccountName=" + UserID + ")";
      Dsearch.PropertiesToLoad.Add("cn");

虽然这到目前为止工作正常,但我必须让你知道我仍然在测试它并且上面的代码没有理由运行所以它会被删除...测试目前包括尝试发现第二组的情况代码是任何更多的用途。同样,这是一项正在进行中的工作,但由于它可以提供一些帮助或者让你的大脑慢慢思考一些想法,我现在决定添加它......一旦所有测试完成,我将用最终结果更新它。

1
Clarence

我正在使用Node,Express和Passport,并且正在努力解决同样的问题。我通过将www-authenticate标头显式设置为空字符串来实现它。就我而言,它看起来像这样:

(err, req, res, next) => {
  if (err) {
    res._headers['www-authenticate'] = ''
    return res.json(err)
  }
}

我希望能帮助别人!

0
John Knotts

对于那些未知的C#,这里的ActionAttribute返回400而不是401,并且'swallows'是基本的auth对话框。

public class NoBasicAuthDialogAuthorizeAttribute : AuthorizeAttribute
{
    protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
    {
        base.HandleUnauthorizedRequest(filterContext);
        filterContext.Result = new HttpStatusCodeResult(400);
    }
}

使用如下:

[NoBasicAuthDialogAuthorize(Roles = "A-Team")]
public ActionResult CarType()
{
 // your code goes here
}

希望这能为您节省一些时间。

0
Matas Vaitkevicius