为什么我的Drupal 8 CORS设置不起作用?

从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(?)。

这有什么不对吗?

在失眠中做同样的要求完全没问题。

响应是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. 您的浏览器在没有Authorization标头的情况下OPTIONS请求发送到服务器,因为OPTIONS检查的全部目的是查看是否可以包含该标头。
  4. 您的服务器看到OPTIONS请求,但不是以指示它允许请求中的Authorization标头的方式响应它,而是因为它缺少标头而拒绝它使用401。
  5. 您的浏览器需要200或204的CORS预检响应,而是获得401响应。 因此,您的浏览器就在那里停止,从不尝试从您的代码中GET请求。

因此,您需要弄清楚当前服务器端代码的哪个部分导致您的服务器需要OPTIONS请求的授权,并且您需要更改它以便在不需要授权的情况下处理OPTIONS请求。

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

除了工作的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' });