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

时间:2012-03-25 10:56:10

标签: javascript jquery rest basic-authentication

我需要使用基本身份验证发送授权请求。我已经使用jquery成功实现了这一点。但是当我得到401错误时,基本的auth浏览器弹出窗口被打开,并且没有调用jquery ajax错误回调。

12 个答案:

答案 0 :(得分:41)

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

  • 将服务器响应更改为不返回401。返回200代码并在jQuery客户端中处理它。
  • 将用于授权的方法更改为标题中的自定义值。浏览器将显示 Basic Digest 的弹出窗口。您必须在客户端和服务器上更改它。

    headers : {
      "Authorization" : "BasicCustom"
    }
    

另请参阅this以获取使用基本身份验证的jQuery的示例。

答案 1 :(得分:31)

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

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

答案 2 :(得分:17)

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

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

如果您收到401错误(用户名或密码错误),将使用jquery错误回调正确处理。它可能会导致一些安全问题(如果是http协议而不是https),但它可以正常工作。

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

答案 3 :(得分:9)

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

这是Apache重写响应以删除WWW-Authenticate头的配置请求包含的IFF包含头X-Requested-With: XMLHttpRequest(默认情况下由主要的Javascript框架设置,如JQuery / AngularJS等。 ..)AND响应包含标题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>   

答案 4 :(得分:5)

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

Guide here

您要更改的值为response_www_authenticate

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

答案 5 :(得分:3)

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

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

答案 6 :(得分:2)

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

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

答案 7 :(得分:2)

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

答案 8 :(得分:1)

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

constructor(props) {
  super(props);
  this.state = {
    location: false,
  };
}

componentDidMount() {
  this.askForUserPermissionToGetCurrentLocation();
}

async askForUserPermissionToGetCurrentLocation() {
  // Ask for user's permission to access location settings
  let { status } = await 
  Expo.Permissions.askAsync(Expo.Permissions.LOCATION);
  console.log(status);
  // User denied access
  if (status !== "granted") {
    console.log("denied");

  // Otherwise, access granted
  } else {
    console.log("permission granted");
    // Get the location
    let location = await Expo.Location.getCurrentPositionAsync({});
    console.log(location);
    this.setState({ location: location });
}

答案 9 :(得分:0)

创建一个/ login url,而不是通过GET接受“user”和“password”参数,并且不需要基本的auth。在这里,使用php,node,java,whatever和解析你的passwd文件并匹配参数(user / pass)。如果匹配则重定向到http://user:pass@domain.com/(这将在您的浏览器上设置凭据)如果没有,则发送401响应(没有WWW-Authenticate标头)。

答案 10 :(得分: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);
            }
        }
    };
}

答案 11 :(得分:0)

尚未探讨修复的原因或范围,但我发现如果我正在执行 fetch 请求并添加标头 x-requested-with: 'XMLHttpRequest',我将不再在 Chrome 中获得弹出式身份验证框并且不需要更改服务器。它正在与节点 http 库对话。看起来 WWW-Authenticate 标头从服务器返回,但 Chrome 处理它的方式不同。可能是指定的。

示例:

fetch(url, {
  headers: {
     Authorization: `Basic ${auth}`,
     'x-requested-with': 'XMLHttpRequest'
  },
  credentials: 'include'
})