如何防止浏览器使用Jquery调用基本身份验证弹出窗口并处理401错误?


Answers:


46

我最近也面临这个问题。由于您无法更改浏览器的默认行为401(在基本身份验证或摘要身份验证的情况下)显示弹出窗口,因此有两种方法可以解决此问题:

  • 将服务器响应更改为不返回401200而是返回一个代码,并在您的jQuery客户端中进行处理。
  • 将用于授权的方法更改为标头中的自定义值。浏览器将显示BasicDigest的弹出窗口。您必须在客户端和服务器上都进行更改。

    headers : {
      "Authorization" : "BasicCustom"
    }

也请看一看对于使用jQuery使用基本身份验证的一个例子。


10
WWW-Authenticate:xBasic realm = com.example可以完成此操作,同时提供经典的401状态代码。这篇博客给我的提示(我不是博客所有者)loudvchar.blogspot.ca/2010/11/...
PM

2
@PM,博客的答案是一个完美的解决方案。请注意,如果使用<security:http-basic/>,则无需定义,basicAuthenticationFilter但应将其定义为<security:http-basic entry-point-ref="myBasicAuthenticationEntryPoint"/>
Brett Ryan

您能告诉我在发送回客户端之前如何覆盖响应吗,我正在使用具有基本auth的jaxrs。我需要重写哪个类来修改响应?
mohammed sameen '17

出于某种原因,我得到恢复时,一个弹出式401WWW-Authenticate:Bearer WWW-Authenticate:NTLM WWW-Authenticate:Negotiate你知道为什么那会是
DevEng

34

返回通用的400状态代码,然后处理该客户端。

或者,您可以保留401,而不返回WWW-Authenticate标头,这实际上是浏览器通过身份验证弹出窗口响应的内容。如果缺少WWW-Authenticate标头,则浏览器将不提示输入凭据。


6
@MortenHaraldsen好吧,在这种情况下,401响应是正确的响应,问题在于浏览器会自动本地处理此问题,而不是允许javascript应用程序处理它。您可以通过不返回标准建议的正确响应来遵循标准,或者可以通过返回标准建议的响应代码来选择不遵循标准。选择:)
Ibraheem

在我的Express应用中,我用以下一行代码修复了该问题: res.removeHeader('www-authenticate'); // prevents browser from popping up a basic auth window.
gstroup

1
@Ibraheem,我自己不能说得更好。标准是由坐下来聊天的人创建的,不一定是坐下来编写代码的人创建的。
user2867288'8

15

您可以使用以下请求网址禁止基本身份验证弹出窗口:

https://username:password@example.com/admin/...

如果您收到401错误(错误的用户名或密码),则会通过jquery错误回调正确处理。它可能会导致一些安全问题(如果使用HTTP协议而不是https),但是它是可行的。

UPD:此解决方案支持将在Chrome 59中删除


惊人!!!!解决了我的问题,因为该问题尝试使用192.168.1.1,并且路由器不断询问Auth。
Nadav Lebovitch 2015年

如果转到开发人员工具下的“网络”标签,则在任何浏览器中,您都可以用纯文本格式读取用户名和密码。虽然可以。
Bruno Finger 2015年

19
请永远不要这样做,现在您的Web服务器上的请求日志对我来说更有价值。.免费的用户名和密码组合以及响应代码!谢谢
雷姆科

但是有人怎么防止用户名和密码被查看
sdx11 '17

3
这种身份验证方法已经过时,Chrome将https://user:pass@host/在2017年6月前后在M59中放弃对嵌入式凭据的支持。有关更多信息,请参阅chromestatus博客文章
Garywoo

13

正如其他人指出的那样,更改浏览器行为的唯一方法是确保响应不包含401状态代码,或者如果响应不包含401 WWW-Authenticate: Basic标头。由于更改状态码不是很语义化也不可取,因此一种好的方法是删除WWW-Authenticate标头。如果您不能或不想修改Web服务器应用程序,则可以始终通过Apache服务或代理它(如果您尚未使用Apache)。

这是Apache的配置,用于重写响应以删除请求包含的WWW-Authenticate标头IFF,该标头包含标头X-Requested-With: XMLHttpRequest(默认情况下由主要的Javascript框架(如JQuery / AngularJS等)设置标头),并且响应包含标头WWW-Authenticate: Basic

已在Apache 2.4上测试(不确定它是否可与2.2一起使用)。这取决于mod_headers正在安装的模块。(在Debian / Ubuntu上,sudo a2enmod headers然后重新启动Apache)

    <Location />
            # Make sure that if it is an XHR request,
            # we don't send back basic authentication header.
            # This is to prevent the browser from displaying a basic auth login dialog.
            Header unset WWW-Authenticate "expr=req('X-Requested-With') == 'XMLHttpRequest' && resp('WWW-Authenticate') =~ /^Basic/"
    </Location>   

1
要对Nginx执行相同操作,请设置proxy_hide_header WWW-Authenticate;
Cuga

7

将X-Requested-With:XMLHttpRequest与您的请求标头一起使用。因此,响应标头将不包含WWW-Authenticate:Basic。

beforeSend: function (xhr) {
                    xhr.setRequestHeader('Authorization', ("Basic "
                        .concat(btoa(key))));
                    xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
                },

1
那对我没有影响。设置XMLHttpRequest时,不包括使用哪种WWW身份验证的服务器?
罗伯特·安东努奇

@RobertAntonucci这是Apache Tomcat
sedhu

5

如果使用的是IIS服务器,则可以设置IIS URL重写(v2)以将WWW-Authentication标头重写为None所请求的URL。

在这里指导

您要更改的值为response_www_authenticate

如果您需要更多信息,请添加评论,然后我将发布web.config文件。


1
效果很好。我想指出,在IIS 7.5的URL Rewrite v2中,“响应”部分必须写为“ RESPONSE_www_authenticate”。
Michael Freeman

3

如果删除了WWW-Authenticate标头,则将不会获得凭据的缓存,也不会在请求中返回Authorization标头。这意味着现在您将必须为生成的每个新请求输入凭据。


这是非常重要的,绝对正确。
Tez Wingfield

2

另外,如果您可以自定义服务器响应,则可以返回403 Forbidden。

浏览器将不会打开身份验证弹出窗口,并且将调用jquery回调。


5
这违反了HTTP 1.1规范,在该规范中声明“ ...授权将无济于事,不应重复请求”。
Jukka Dahlbom

1
在对您不允许访问的资源进行身份验证时,接收到403是有效的;应该在尚未经过身份验证的位置发送401。
Brett Ryan

1

在Safari中,您可以使用同步请求来避免浏览器显示弹出窗口。当然,在这种情况下,同步请求仅应用于检查用户凭据...您可以在发送实际请求之前使用此类请求,如果内容(已发送或已接收)非常繁重,可能会导致不良的用户体验。

    var xmlhttp=new XMLHttpRequest;
    xmlhttp.withCredentials=true;
    xmlhttp.open("POST",<YOUR UR>,false,username,password);
    xmlhttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");
    xmlhttp.setRequestHeader('X-Requested-With', 'XMLHttpRequest');

在其他情况下,使用“ OPTIONS”代替“ POST”也可能会有所帮助。
伊曼纽·塞利尔

0

创建一个/ login网址,然后通过GET接受“ user”和“ password”参数,并且不需要基本身份验证。在这里,使用php,node,java等工具,解析您的passwd文件并匹配参数(用户/密码)。如果匹配,则重定向到http:// user:pass@domain.com/(这将在您的浏览器上设置凭据),如果不匹配,则发送401响应(不带WWW-Authenticate标头)。


对于任何试图在中间攻击中从纯文本文件中嗅探用户名/密码的人来说,这都是非常好的!
Ajax

0

从Spring Boot的背面,我使用了自定义的BasicAuthenticationEntryPoint:

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.cors().and().authorizeRequests()
            ...
            .antMatchers(PUBLIC_AUTH).permitAll()
            .and().httpBasic()
//    https://www.baeldung.com/spring-security-basic-authentication
            .authenticationEntryPoint(authBasicAuthenticationEntryPoint())
            ...

@Bean
public BasicAuthenticationEntryPoint authBasicAuthenticationEntryPoint() {
    return new BasicAuthenticationEntryPoint() {
        {
            setRealmName("pirsApp");
        }

        @Override
        public void commence
                (HttpServletRequest request, HttpServletResponse response, AuthenticationException authEx)
                throws IOException, ServletException {
            if (request.getRequestURI().equals(PUBLIC_AUTH)) {
                response.sendError(HttpStatus.PRECONDITION_FAILED.value(), "Wrong credentials");
            } else {
                super.commence(request, response, authEx);
            }
        }
    };
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.