【问题标题】:Why is my Drupal 8 CORS setup not working?为什么我的 Drupal 8 CORS 设置不起作用?
【发布时间】:2017-12-25 21:12:26
【问题描述】:

从 Drupal 8.2 开始,cors 设置在核心中。在我的services.yml(和default.services.yml)中,我有以下设置:

cors.config:
    enabled: true
    # Specify allowed headers, like 'x-allowed-header'.
    allowedHeaders: ['x-csrf-token','authorization','content-type','accept','origin','x-requested-with']
    # Specify allowed request methods, specify ['*'] to allow all possible ones.
    allowedMethods: ['*']
    # Configure requests allowed from specific origins.
    allowedOrigins: ['*']
    # Sets the Access-Control-Expose-Headers header.
    exposedHeaders: false
    # Sets the Access-Control-Max-Age header.
    maxAge: 1000
    # Sets the Access-Control-Allow-Credentials header.
    supportsCredentials: true

我的域 a.com 受 htaccess 密码保护。

在域 b.com 上,我尝试从域 a.com 加载一些 API:

$.ajaxSetup({
  xhrField: {
    withCredentials : true
  },
  beforeSend: function (xhr) {
    xhr.setRequestHeader('Authorization', 'Basic Z2VuaXVzOmNvYXRpbmdz');
  }
});

request = $.ajax({
  url: apiBaseUrl + 'api/foobar',
  dataType: 'json',
  type: 'get',
  password: 'foo',
  username: 'bar'
});

在 chrome 中它工作正常,在 Firefox 中我得到一个错误。请求头:

Access-Control-Request-Method: GET
Access-Control-Request-Headers: authorization

响应是 401“需要授权”,它说请求方法是 OPTIONS (?)。

这里有什么问题?

insomnia 中执行相同的请求效果很好。

【问题讨论】:

  • 你确定你在 Firefox 中看到的问题不仅仅是因为它正在加载它在服务器端添加 CORS 配置之前缓存的文档的缓存副本吗?您是否尝试过清除 Firefox 中的浏览器缓存?
  • 并且要清楚为什么您会看到请求方法为 OPTIONS 的指示:这是因为请求中存在 Authorization 请求标头会触发您的浏览器自动进行 CORS 预检 OPTIONS在尝试您的代码尝试发送的 GET 请求之前请求 developer.mozilla.org/en-US/docs/Web/HTTP/…
  • 请求在 insomnia 中起作用的原因是因为没有对 insomnia 发出跨域请求的能力施加任何限制,而相比之下,浏览器会阻止您的前端 JavaScript 代码能够访问来自跨域的响应。源请求,除非这些响应包括 Access-Control-Allow-Origin 响应标头和任何其他必要的 CORS 响应标头。 developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS有详情
  • 在Firefox中,我的5个ajax json请求之一在特定的$.ajax()调用(或对象)中不起作用,除了ajaxSetup中的withCredentialsusername和@987654336 @ 值对存在。 chrome 和 safari 显然忽略了这些,而 firefox 则不会。

标签: jquery ajax drupal cors drupal-8


【解决方案1】:

响应是 401“需要授权”,它说请求方法是 OPTIONS (?)。

您需要将服务器后端配置为不需要对OPTIONS 请求进行授权。

该 401 响应表明服务器要求对 OPTIONS 请求进行授权,但授权失败,因为该请求不包含所需的凭据。

原因是,OPTIONS 请求是作为 CORS 的一部分由您的浏览器自动发送的。

https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS#Preflighted_requests 一般解释了为什么浏览器会进行 CORS 预检 OPTIONS 请求,但在问题的特定情况下,原因是因为请求包含 Authorization 请求标头。

所以发生的事情是:

  1. 您的代码告诉您的浏览器它想要发送带有 Authorization 标头的请求。
  2. 您的浏览器显示,好的,带有 Authorization 标头的请求要求我执行 CORS 预检 OPTIONS 以确保服务器允许带有 Authorization 标头的请求。
  3. 您的浏览器将OPTIONS 请求发送到服务器没有Authorization 标头,因为OPTIONS 检查的全部目的是查看是否可以包含该标头。
  4. 您的服务器看到 OPTIONS 请求,但它没有以表明它允许请求中的 Authorization 标头的方式对其进行响应,而是以 401 拒绝它,因为它缺少标头。
  5. 您的浏览器期望 CORS 预检得到 200 或 204 响应,但得到的是 401 响应。因此,您的浏览器会停在那里,并且永远不会尝试来自您的代码的 GET 请求。

因此,您需要弄清楚当前服务器端代码的哪一部分导致您的服务器需要对OPTIONS 请求的授权,并且您需要更改它以便它处理OPTIONS 请求而不需要授权.

一旦您解决了这个问题,问题中显示的现有 cors.config 应该会导致服务器以正确的方式响应 OPTIONS 请求 - 使用包含 AuthorizationAccess-Control-Allow-Headers 响应标头,以便您的然后浏览器可以说,好的,这个服务器允许包含Authorization 标头的跨域请求,所以我现在继续发送实际的GET 请求。

【讨论】:

  • 我向上帝发誓,这正是我所尝试的。我还添加了SetEnvIfNoCase Request_Method OPTIONS allowed,但它一开始没有用。不过,感谢您的精彩总结!
  • 我在 Firefox 中仍然遇到问题。在网络选项卡中,我看到响应实际上返回了有效的 json,但在 jQuery 中它给了我一个错误,即它进入 fail 而不是 done 函数。 statusText 是错误的,没有任何进一步的 responseText
  • 如果 Firefox 没有看到正确的 CORS 响应,预计您仍然可以在 devtools 网络选项卡中看到响应。但仅仅因为你可以看到它并不意味着 Firefox 会允许你的代码访问响应。如果 Firefox 在响应中看到 Access-Control-Allow-Origin 并具有正确的值,它只会让您访问响应。
  • 无论如何,为了进一步隔离问题,您可以考虑的一件事是直接使用 fetch(...) 方法而不是 jQuery $.ajax 编写请求代码。我对 jQuery $.ajax 的各种选项的效果并不十分熟悉——这些选项在幕后是什么原因——但我更熟悉使用本机 fetch() 解决问题
【解决方案2】:

除了有效的 CORS 配置和 htaccess 设置:

SetEnvIfNoCase Request_Method OPTIONS noauth
Order Deny,Allow
Deny from all
Require valid-user
Allow from env=noauth
Satisfy Any

您必须确保您的 ajax 设置没有 withCredentialspasswordusername,就像我的问题一样。至少,这会导致 Firefox 出现错误。工作 ajax:

$.ajaxSetup({
  xhrField: {
    withCredentials : true
  },
  beforeSend: function (xhr) {
    xhr.setRequestHeader('Authorization', 'Basic foobarbarfoo');
  }
});

request = $.ajax({
  url: isApiActive ? apiBaseUrl + 'api/mydata' : './mydata.json',
  dataType: 'json',
  type: 'get'
});

【讨论】:

  • 真的很高兴听到你想出了一个完整的解决方案,很高兴我可以不再让它让我担心:)这一天——所以会在大约 14 小时后绕回来,然后再做。)
  • 我在您的回答下的最后一条评论是我想通了,希望您没有监督:D 再次感谢伙计!
猜你喜欢
  • 2015-05-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-01-11
  • 2018-12-10
  • 2015-05-02
  • 2023-03-14
相关资源
最近更新 更多