为啥 Chrome 和 Firefox 使用基本身份验证的 CORS ajax 调用的行为不同?

Posted

技术标签:

【中文标题】为啥 Chrome 和 Firefox 使用基本身份验证的 CORS ajax 调用的行为不同?【英文标题】:Why Chrome and Firefox have not the same behaviour with CORS ajax call with basic auth?为什么 Chrome 和 Firefox 使用基本身份验证的 CORS ajax 调用的行为不同? 【发布时间】:2016-01-06 06:57:45 【问题描述】:

对于上下文,我正在尝试跨站点调用一个 API,该 API 需要用户使用基本身份验证进行身份验证。 为 API 提供服务的 Tomcat (7.0.43) 设置为允许通过身份验证进行跨域调用。

我正在使用 jquery.ajax,传递以下选项:

xhrOtpions = 
        url: "http://localhost:8080/api/v1/ressource",
        dataType: 'json',
        username: "user",
        password: "pass",
        xhrFields: 
          withCredentials: true
        
      

使用 Chrome (45),请求成功,使用 Firefox (41),不发送请求,错误消息为 Access to restricted URI denied

为了在 Firefox 上进行调用,我更改了选项以应用我从相关 jquery 问题on github 中读取的内容:

xhrActiveBuilds = 
        url: "http://localhost:8080/api/v1/ressource",
        dataType: 'json',
        username: "user",
        password: "pass",
        xhrFields: 
          withCredentials: true
        ,            
        beforeSend: function (xhr) 
          xhr.setRequestHeader ("Authorization",  "Basic <encoded_credentials>")
        
      

这对 FF 没有任何改变,仍然是同样的错误。 在 Chrome 上,现在发送了一个预检 OPTIONS 请求,该请求失败并显示 403 禁止响应代码。

Tomcat服务器的CORS过滤器配置下方:

 <filter>
    <filter-name>CorsFilter</filter-name>
      <filter-class>org.apache.catalina.filters.CorsFilter</filter-class>
    <init-param>
      <param-name>cors.allowed.origins</param-name>
      <param-value>http://localhost:1081</param-value>
    </init-param>
    <init-param>
      <param-name>cors.allowed.methods</param-name>
      <param-value>GET,POST,HEAD,OPTIONS,PUT</param-value>
    </init-param>
    <init-param>
      <param-name>cors.allowed.headers</param-name>
      <param-value>Content-Type,X-Requested-With,accept,Origin,Access-Control-Request-Method,Access-Control-Request-Headers</param-value>
    </init-param>
    <init-param>
      <param-name>cors.exposed.headers</param-name>
      <param-value>Access-Control-Allow-Origin,Access-Control-Allow-Credentials,Access-Control-Allow-Authorization</param-value>
    </init-param>
    <init-param>
      <param-name>cors.support.credentials</param-name>
      <param-value>true</param-value>
    </init-param>
    <init-param>
      <param-name>cors.preflight.maxage</param-name>
      <param-value>10</param-value>
    </init-param>
</filter>
<filter-mapping>
  <filter-name>CorsFilter</filter-name>
  <url-pattern>/*</url-pattern>
</filter-mapping>

【问题讨论】:

“在 Chrome 上,现在发送了一个预检 OPTIONS 请求,但由于 403 禁止响应代码而失败” 修复此问题,两个浏览器都可以工作。您的服务器应该支持 OPTIONS 预检请求。 developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS @KevinB tomcat 服务器已经配置为允许 OPTIONS 请求: cors.allowed.methodsGET,POST ,HEAD,OPTIONS,PUT 那么为什么在发送选项请求时它会在 chrome 中为您提供 403 呢?显然某些服务器端配置不正确。或者您没有发送服务器所期望的内容。我们都无法为您调试。 在设置凭据时也可能发生预检。并非所有浏览器都以相同的方式解释规范。 【参考方案1】:

我终于弄清楚了这两个问题。

服务器端:我在 cors.allowed.headers 中添加了 authorization

客户端:我将选项替换为:

xhrActiveBuilds = 
  url: "http://localhost:8080/api/v1/ressource",
  dataType: 'json',
  xhrFields:  withCredentials: true ,
  beforeSend: function (xhr) 
    xhr.setRequestHeader ("Authorization",  "Basic <encoded_credentials>")
  

请注意,我已删除用户名和密码,因为它们导致 FF 上的请求因 jQuery 实现而失败 (see)

【讨论】:

以上是关于为啥 Chrome 和 Firefox 使用基本身份验证的 CORS ajax 调用的行为不同?的主要内容,如果未能解决你的问题,请参考以下文章

为啥 firefox/chrome 响应式仿真和智能手机之间的区别?

为啥 Chrome 和 Firefox 显示不同的 flex 布局结果?

为啥 Firefox 对待 Helvetica 和 Chrome 的方式不同?

为啥我对表格的媒体查询可以在 chrome 中使用,而不是在 firefox 中使用?

为啥 Chrome 和 Firefox 以不同方式处理 jQuery ajax() 回调中设置的 javascript 变量?

为啥 Chrome 和 Firefox 以不同方式处理 jQuery ajax() 回调中设置的 javascript 变量?