我怎样才能禁止浏览器的身份validation对话框?

我的Web应用程序有一个login页面,通过AJAX调用提交authentication凭证。 如果用户input正确的用户名和密码,一切都很好,但是如果没有的话,会发生以下情况:

  1. Web服务器确定,虽然请求包含格式正确的授权标头,但标头中的凭证无法成功进行身份validation。
  2. Web服务器返回一个401状态代码,并包含一个或多个WWW-Authenticate标题,其中列出了支持的authenticationtypes。
  3. 浏览器检测到我对XMLHttpRequest对象的调用的响应是401,响应包括WWW-Authenticate标头。 然后popup一个authentication对话框,询问用户名和密码。

直到第3步,这一切都很好。我不想popup对话框,我想要在我的AJAXcallback函数中处理401响应。 (例如,通过在login页面上显示一条错误消息。)我希望用户重新input他们的用户名和密码,当然,但我希望他们看到我友好,令人放心的login表单,而不是浏览器的丑陋,默认authentication对话框。

顺便说一句,我没有控制服务器,所以让它返回一个自定义的状态代码(即,除了401以外的东西)不是一个选项。

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


编辑
作者补充资料(9月18日):
我应该补充一点,浏览器popup的validation对话框的真正问题是它给用户提供的信息不足。

用户刚刚通过login页面上的表单input了用户名和密码,他认为他已经正确input了他们,并且点击了提交button或者回车。 他的期望是他会被带到下一页,或者被告知他错误地input了他的信息,应该再试一次。 但是,他却出现了一个意想不到的对话框。

该对话不会确认他刚input用户名和密码的事实。 没有明确说明有问题,应该再试一次。 相反,对话框会向用户显示隐藏的信息,如“网站说:' [realm] '”。 其中[realm]是一个只有程序员可以爱的短域名。

网页浏览器devise师注意到:如果对话框本身更简单易用,没有人会问如何取消authentication对话框。 我做login表单的全部原因是我们的产品pipe理团队正确地认为浏览器的authentication对话框是可怕的。

我不认为这是可能的 – 如果你使用浏览器的HTTP客户端实现,它会一直popup该对话框。 两个黑客想到:

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

  2. 您可以为您在自己的服务器上访问的服务设置一个'proxie',并让它稍微修改authentication头,以便浏览器不会识别它们。

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

副作用是不显示默认身份validationpopup窗口。

确保您的API调用将X-Requested-With标头设置为XMLHttpRequest 。 如果是这样,除了根据这个良好的做法来改变服务器的行为,什么都不做。

当满足以下两个条件时,浏览器popuplogin提示符:

  1. HTTP状态是4xx
  2. WWW-Authenticate标题出现在响应中

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

如果您无法控制响应,则可以设置代理以从响应中筛选出WWW-Authenticate标头。

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

在Mozilla中,当你创buildXMLHttpRequest对象时,你可以用下面的脚本实现它:

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

第二行禁止对话框….

我意识到这个问题和答案是非常古老的。 但是,我在这里结束了。 也许别人也是如此。

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

从403上的IETF文件:

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

你使用哪种服务器技术?是否有一个特定的产品用于身份validation?

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

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

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

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

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

到目前为止它已经工作,因为家庭控制器下的索引动作validation用户。 如果login失败,则此操作中的视图具有login控件,用于使用传递到目录服务的LDAP查询使用用户login:

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

虽然迄今为止这一切都很好,但我必须让你知道,我仍在testing它,上面的代码没有理由运行,所以它可能会被删除…testing目前包括试图发现一个情况下,第二组的代码是更多的使用。 再次,这是一个正在进行的工作,但是由于它可能会有一些帮助或者慢慢地让大脑产生一些想法,所以我决定现在添加它…我将在所有testing完成后用最终结果更新它。

对于那些解开C#的人ActionAttribute ,这里的ActionAttribute返回400而不是401 ,并且“吞噬”基本authentication对话框。

 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 } 

希望这可以为你节省一些时间。

我正在使用节点,快递和护照,并在同一个问题挣扎。 我明白地设置了www-authenticate头部为一个空string来工作。 就我而言,它看起来像这样:

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

我希望能帮助别人!