nginx错误:“访问控制允许来源”标头包含多个值

nginx错误:“访问控制允许来源”标头包含多个值,nginx,Nginx,我曾经使用以下配置运行nginx v1.6: location / { alias /some/path/; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $sc

我曾经使用以下配置运行nginx v1.6:

location / {
    alias                   /some/path/;
    proxy_set_header        X-Real-IP $remote_addr;
    proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header        X-Forwarded-Proto $scheme;
    proxy_set_header        uuid $uuid;
    more_set_headers        'Access-Control-Allow-Origin: $http_origin';
    more_set_headers        'Access-Control-Allow-Credentials: true';
    more_set_headers        'Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS';
    more_set_headers        'Access-Control-Allow-Headers: DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,access_token,__setXHR_';
    if ($request_method = 'OPTIONS') {
        more_set_headers    'Access-Control-Allow-Origin: $http_origin';
        more_set_headers    'Access-Control-Allow-Credentials: true';
        more_set_headers    'Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS';
        more_set_headers    'Access-Control-Allow-Headers: DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,access_token,__setXHR_';
        add_header          'Access-Control-Max-Age' 1728000;
        add_header          'Content-Type' 'text/plain charset=UTF-8';
        add_header          'Content-Length' 0;
        return              204;
    }
}
自从我升级到nginx v1.10.x以来,更多的_-set_头不再工作,我一直通过添加_头'blabla'来改变它

现在看起来是这样的:

location / {
    alias                   /some/path/;
    proxy_set_header        X-Real-IP $remote_addr;
    proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header        X-Forwarded-Proto $scheme;
    proxy_set_header        uuid $uuid;
    add_header              'Access-Control-Allow-Origin: $http_origin' always;
    add_header              'Access-Control-Allow-Credentials: true' always;
    add_header              'Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS' always;
    add_header              'Access-Control-Allow-Headers: DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,access_token,__setXHR_' always;
    if ($request_method = 'OPTIONS') {
        add_header          'Access-Control-Allow-Origin: $http_origin' always;
        add_header          'Access-Control-Allow-Credentials: true' always;
        add_header          'Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS' always;
        add_header          'Access-Control-Allow-Headers: DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,access_token,__setXHR_' always;
        add_header          'Access-Control-Max-Age' 1728000;
        add_header          'Content-Type' 'text/plain charset=UTF-8';
        add_header          'Content-Length' 0;
        return              204;
    }
}
但是,当我现在进入网站时,我有以下错误:

加载失败:对飞行前请求的响应未通过访问控制检查:“访问控制允许来源”标题包含多个值“$http\U来源:始终”,但只允许一个值。因此,不允许“源”访问


我应该做什么改变才能让它工作?我有点被卡住了。

但是你添加了两次相同的标题。 在请求方法检查之后不需要添加头,因为在任何情况下都是在上面添加的。 所以我认为您的配置应该如下所示:

location / {
    alias                   /some/path/;
    proxy_set_header        X-Real-IP $remote_addr;
    proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header        X-Forwarded-Proto $scheme;
    proxy_set_header        uuid $uuid;
    add_header              'Access-Control-Allow-Origin: $http_origin' always;
    add_header              'Access-Control-Allow-Credentials: true' always;
    add_header              'Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS' always;
    add_header              'Access-Control-Allow-Headers: DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,access_token,__setXHR_' always;
    if ($request_method = 'OPTIONS') {
        add_header          'Access-Control-Max-Age' 1728000;
        add_header          'Content-Type' 'text/plain charset=UTF-8';
        add_header          'Content-Length' 0;
        return              204;
    }
}

但是您添加了两次相同的标题。 在请求方法检查之后不需要添加头,因为在任何情况下都是在上面添加的。 所以我认为您的配置应该如下所示:

location / {
    alias                   /some/path/;
    proxy_set_header        X-Real-IP $remote_addr;
    proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header        X-Forwarded-Proto $scheme;
    proxy_set_header        uuid $uuid;
    add_header              'Access-Control-Allow-Origin: $http_origin' always;
    add_header              'Access-Control-Allow-Credentials: true' always;
    add_header              'Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS' always;
    add_header              'Access-Control-Allow-Headers: DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,access_token,__setXHR_' always;
    if ($request_method = 'OPTIONS') {
        add_header          'Access-Control-Max-Age' 1728000;
        add_header          'Content-Type' 'text/plain charset=UTF-8';
        add_header          'Content-Length' 0;
        return              204;
    }
}
找到解决方案

这只是一个语法错误

add_header              'Access-Control-Allow-Origin: $http_origin' always;
一定是

add_header              'Access-Control-Allow-Origin' '$http_origin' always;
当然,对所有其他的添加头条目进行相同的修改。

找到了解决方案

这只是一个语法错误

add_header              'Access-Control-Allow-Origin: $http_origin' always;
一定是

add_header              'Access-Control-Allow-Origin' '$http_origin' always;

当然,对所有其他的添加标题条目也进行了同样的修改。

我记不起今天早些时候在哪里读到了这篇文章。我把那一页弄丢了。然而,我的回答是:

不能在堆栈中设置多个cors标头。例如nginx和django。他们中只有一个能做这项工作,否则会有多个 标题中的值

通过从我的api中删除cors处理,并且只让nginx这样做,错误消失了

我会更新它,并在找到它时参考源代码。 由于很难在谷歌的多个论坛和平台上找到这些信息,我决定回答这个显而易见的问题

更新2021-更多解释

对于那些好奇的人,我想再详细阐述一下。CORS标头实际上只能包含一个值。如果它是一个*允许所有,那没关系,但是如果你想允许两个特定的IP呢?您可能希望在标头中写入这两个IP,这是无效的

当使用web框架ala Express.js或Django时,所有这些包在幕后都做了以下工作

它们将来自传入请求referer头的IP与开发人员提供的IP列表相匹配。如果存在匹配项,响应将在CORS头中添加该特定IP。没有其他IP

如果您想要实现自己的CORS中间件,则需要复制所描述的行为


Nginx很可能做同样的事情,而双方都不检查头中是否已经有值。他们只是根据匹配添加值。因此,结果将是一个无效的CORS标题。

我记不起今天早些时候在哪里读到的。我把那一页弄丢了。然而,我的回答是:

不能在堆栈中设置多个cors标头。例如nginx和django。他们中只有一个能做这项工作,否则会有多个 标题中的值

通过从我的api中删除cors处理,并且只让nginx这样做,错误消失了

我会更新它,并在找到它时参考源代码。 由于很难在谷歌的多个论坛和平台上找到这些信息,我决定回答这个显而易见的问题

更新2021-更多解释

对于那些好奇的人,我想再详细阐述一下。CORS标头实际上只能包含一个值。如果它是一个*允许所有,那没关系,但是如果你想允许两个特定的IP呢?您可能希望在标头中写入这两个IP,这是无效的

当使用web框架ala Express.js或Django时,所有这些包在幕后都做了以下工作

它们将来自传入请求referer头的IP与开发人员提供的IP列表相匹配。如果存在匹配项,响应将在CORS头中添加该特定IP。没有其他IP

如果您想要实现自己的CORS中间件,则需要复制所描述的行为


Nginx很可能做同样的事情,而双方都不检查头中是否已经有值。他们只是根据匹配添加值。因此,结果将是一个无效的CORS头。

基于傻瓜的解释。 我通过阻止nginx通过delete proxy\u set\u header Host$Host设置头来解决这个问题;从nginx配置

server {
   ....
   location / {
      ...
   #  proxy_set_header Host $host;  
   }}
 

基于愚人的解释。 我通过阻止nginx通过delete proxy\u set\u header Host$Host设置头来解决这个问题;从nginx配置

server {
   ....
   location / {
      ...
   #  proxy_set_header Host $host;  
   }}
 

add_header将追加值而不是替换它

add_header将追加值而不是替换它

是,尝试了,但收到另一条错误消息:响应飞行前请求d
oesn未通过访问控制检查:请求的资源上不存在“访问控制允许来源”标头。因此不允许源站访问。是的,尝试了,但收到另一条错误消息:对飞行前请求的响应未通过访问控制检查:请求的资源上不存在“访问控制允许源站”标头。因此,不允许访问Origin。我认为您提到了这一点。已经有一段时间了。谢谢你添加更多信息。我想你提到了这一点。已经有一段时间了。感谢您添加更多信息。事实上,如果您已经在堆栈中的任何其他位置进行了此操作,您应该在nginx上既不允许也不拒绝此操作。这就是我的答案。您不应该在nginx中设置此标头。但在我看来,最好在nginx上设置所有头文件,而不要在应用程序级别上这样做。事实上,如果您已经在堆栈中的其他任何地方这样做了,那么在nginx上也不应该允许或拒绝这样做。这就是我的答案。您不应该在nginx中设置此标头。但在我看来,最好在nginx上设置所有头文件,而不要在应用程序级别设置。