如何解决:对飞行前请求的响应未通过访问控制检查:没有“ Access-Control-Allow-Origin”标头

时间:2019-10-15 14:55:49

标签: reactjs .htaccess docker cors

我正在尝试使用php后端和React JS前端构建一个简单的API。我为此使用了两个单独的docker容器(api.dev.de和react.dev.de。这是必需的。我使用的是nginx代理的稍作修改的版本。但是,当我通过React获取时发送请求时()发送到服务器,出现错误:

  

可从以下位置访问“ https://api.dev.de/index.php?read=users”     源'https://react.dev.de'已被CORS政策阻止:     对预检请求的响应未通过访问控制检查:否     请求中存在“ Access-Control-Allow-Origin”标头     资源。如果不透明的响应满足您的需求,请设置请求的     模式设置为“ no-cors”,以在禁用CORS的情况下获取资源。

在下面,您可以看到我要发出的请求和.htaccess文件。

我已经查找了一些对其他人有用的解决方案,包括this 我也写到Dockerfile中的文件(首先在docker-compose.yml中启用此映像的扩展名)。

此外,我还通过挖掘 this 回答并浏览与其他文章的链接以建立一些知识,但仍然没有成功...

这是我的代码段。

Persons.js:

...

fetch('https://api.dev.de/index.php?read=users', {
      method: 'POST',
      headers: {
        'Authorization': 'Basic ' + btoa("<secretName>:<secretPass>"),
        'Accept': 'application/json',
        'Content-Type': 'application/json',
      }
    })

...

.htaccess:

Authtype Basic
AuthName "Protected section. Only for developers."
AuthUserFile /var/www/html/App/.htpasswd
Require valid-user

Header set Access-Control-Allow-Origin "*"
Header set Access-Control-Allow-Credentials "true"

Dockerfile中的配置:

FROM thecodingmachine/php:7.3-v2-apache

...

RUN a2enmod headers

...

执行该功能时,我得到了那些控制台日志:

  

可以从以下网址访问“ https:// api.dev.de/index.php?read=users”       原点“ https:// react.dev.de”已被CORS政策阻止:       对预检请求的响应未通过访问控制检查:否       请求中存在“ Access-Control-Allow-Origin”标头       资源。如果不透明的响应满足您的需求,请设置       请求的模式设置为“ no-cors”,以使用CORS获取资源       禁用。

     

VM2133:1 POST https://api.dev.de/index.php?read=users       净:: ERR_FAILED

但是,当我删除.htaccess文件中的所有身份验证配置以及从Persons.js文件中删除AuthorizationContent-Type部分时,我得到一个有效的响应。但是我不能仅仅从页面中排除我的授权。

当我构建React App并将其粘贴到与API相同的docker容器中,然后调用它时,一切工作正常。因此,我假设它是docker容器的配置(如果我错了,请纠正我)。

更新:

从昨天开始,我尝试了不同的方法,并提出了最后一个问题。

我的fetch()函数现在如下所示:

fetch('https://api.dev.de/index.php?read=users&pass=<password>', {
      method: 'GET',
      headers: {
        'Content-Type': 'multipart/form-data',
        'Accept': 'application/json'
      },
    })

我还更改了.htaccess文件:

# Enabled in the Dockerfile but still checking if it is enabled.
<IfModule mod_headers.c>
    Header set Access-Control-Allow-Origin "*"
    Header set Access-Control-Content-Type "*"
    Header set Access-Control-Accept "*"
    # This should enable the authentication header
    Header set Access-Control-Allow-Credentials "true"
</IfModule>

现在该请求有效,但是当我更改fetch()函数以向其发送授权标头('Authorization': 'Basic: ' + btoa('<username>:<password>'))和.htaccess时:

Authtype Basic
AuthName "Protected section. Only for developers."
AuthUserFile /var/www/html/App/.htpasswd
Require valid-user

<IfModule mod_headers.c>
    Header set Access-Control-Allow-Origin "*"
    Header set Access-Control-Content-Type "*"
    Header set Access-Control-Accept "*"
    # This should enable the authentication header
    Header set Access-Control-Allow-Credentials "true"
</IfModule>

我仍然收到错误:

  

从原点“ https://api.dev.de/index.php?read=users&pass=crud_restAPI_call”到“ https://react.dev.de”的获取操作已被CORS策略阻止:对预检请求的响应未通过访问控制检查:否“ Access-Control-Allow-来源的标头出现在请求的资源上。如果不透明的响应满足您的需求,请将请求的模式设置为“ no-cors”以在禁用CORS的情况下获取资源。

这是因为.htaccess的顺序还是我需要修改其他内容?

更新2:

在我的研究中,我找到了类似问题的答案:“预检请求(OPTIONS),这是我遇到未经授权的401的原因。我认为这是因为我读到OPTIONS去除了一些标头,包括Authentication标头,因此如果没有它,就无法进行认证。”

来源:https://github.com/axios/axios/issues/2076

查看developer.mozilla.org指南(https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch#Sending_a_request_with_credentials_included),我想始终发送凭据(以获取预检请求成功)。

但是,这不起作用...

有人知道为什么不这么做吗?

更新了fetch()函数:

fetch('https://api.dev.de/index.php?read=users&pass=<password>', {
      method: 'POST',
      credentials: 'include',
      headers: {
        'Authorization': 'Basic: ' + btoa('<secretName>:<secretPass>'),
        'Content-Type': 'multipart/form-data',
        'Accept': 'application/json'
      },
    })

我仍然遇到相同的错误:

  

从原点“ https://api.dev.de/index.php?read=users&pass=crud_restAPI_call”到“ https://react.dev.de”的获取操作已被CORS策略阻止:对预检请求的响应未通过访问控制检查:否“ Access-Control-Allow-来源的标头出现在请求的资源上。如果不透明的响应满足您的需求,请将请求的模式设置为“ no-cors”以在禁用CORS的情况下获取资源。

1 个答案:

答案 0 :(得分:0)

预检请求不是与Docker相关的问题,它们是与浏览器相关的策略。您正在使用HTTP标头来触发预检机制,在您的情况下使用“ Authorization”标头,并从您的网站域到api.dev.de域进行跨域调用。

您可以read this article关于避免飞行前检查。

我只需要向您的api服务器添加一个终结点,即可使用适当的CORS相关标头(例如OPTIONS)来响应所有Access-Control-Allow-Origin请求