How to prevent browser to invoke basic auth popup and handle 401 error using Jquery?

陌路散爱 提交于 2019-11-26 08:59:03

问题


I need to send authorization request using basic auth. I have successfully implemented this using jquery. However when I get 401 error basic auth browser popup is opened and jquery ajax error callback is not called.


回答1:


I was facing this issue recently, too. Since you can't change the browser's default behavior of showing the popup in case of a 401 (basic or digest authentication), there are two ways to fix this:

  • Change the server response to not return a 401. Return a 200 code instead and handle this in your jQuery client.
  • Change the method that you're using for authorization to a custom value in your header. Browsers will display the popup for Basic and Digest. You have to change this on both the client and the server.

    headers : {
      "Authorization" : "BasicCustom"
    }
    

Please also take a look at this for an example of using jQuery with Basic Auth.




回答2:


Return a generic 400 status code, and then process that client-side.

Or you can keep the 401, and not return the WWW-Authenticate header, which is really what the browser is responding to with the authentication popup. If the WWW-Authenticate header is missing, then the browser won't prompt for credentials.




回答3:


You can suppress basic auth popup with request url looking like this:

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

If you get 401 error (wrong username or password) it will be correctly handled with jquery error callback. It can cause some security issues (in case of http protocol instead of https), but it's works.

UPD: This solution support will be removed in Chrome 59




回答4:


As others have pointed out, the only way to change the browser's behavior is to make sure the response either does not contain a 401 status code or if it does, not include the WWW-Authenticate: Basic header. Since changing the status code is not very semantic and undesirable, a good approach is to remove the WWW-Authenticate header. If you can't or don't want to modify your web server application, you can always serve or proxy it through Apache (if you are not using Apache already).

Here is a configuration for Apache to rewrite the response to remove the WWW-Authenticate header IFF the request contains contains the header X-Requested-With: XMLHttpRequest (which is set by default by major Javascript frameworks such as JQuery/AngularJS, etc...) AND the response contains the header WWW-Authenticate: Basic.

Tested on Apache 2.4 (not sure if it works with 2.2). This relies on the mod_headers module being installed. (On Debian/Ubuntu, sudo a2enmod headers and restart 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>   



回答5:


If you're using an IIS Server, you could setup IIS URL Rewriting (v2) to rewrite the WWW-Authentication header to None on the requested URL.

Guide here.

The value you want to change is response_www_authenticate.

If you need more info, add a comment and I'll post the web.config file.




回答6:


Use X-Requested-With: XMLHttpRequest with your request header. So the response header will not contain WWW-Authenticate:Basic.

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



回答7:


Alternatively, if you can customize your server response, you could return a 403 Forbidden.

The browser will not open the authentication popup and the jquery callback will be called.




回答8:


If WWW-Authenticate header is removed, then you wont get the caching of credentials and wont get back the Authorization header in request. That means now you will have to enter the credentials for every new request you generate.




回答9:


In Safari, you can use synchronous requests to avoid the browser to display the popup. Of course, synchronous requests should only be used in this case to check user credentials... You can use a such request before sending the actual request which may cause a bad user experience if the content (sent or received) is quite heavy.

    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');



回答10:


Make an /login url, than accept "user" and "password" parameters via GET and don't require basic auth. Here, use php, node, java, whatever and parse your passwd file and match parameters (user/pass) against it. If there is a match then redirect to http://user:pass@domain.com/ (this will set credential on your browser) if not, send 401 response (without WWW-Authenticate header).




回答11:


From back side with Spring Boot I've used custom 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);
            }
        }
    };
}


来源:https://stackoverflow.com/questions/9859627/how-to-prevent-browser-to-invoke-basic-auth-popup-and-handle-401-error-using-jqu

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!