“Access-Control-Allow-Origin”头包含多个值

147
我正在客户端使用AngularJS $http访问服务器端的ASP.NET Web API应用程序的一个终结点。由于客户端托管在与服务器不同的域中,因此需要CORS。$http.post(url, data)可以工作。但是,一旦我验证了用户并通过$http.get(url)发出请求,我就会收到以下消息:
The 'Access-Control-Allow-Origin' header contains multiple values 'http://127.0.0.1:9000, http://127.0.0.1:9000', but only one is allowed. Origin 'http://127.0.0.1:9000' is therefore not allowed access.
Fiddler向我展示,在成功进行选项请求后,get请求中确实有两个头条目。我在哪里做错了?
更新: 当我使用jQuery $.get而不是$http.get时,出现相同的错误消息。所以这似乎不是AngularJS的问题。那么问题出在哪里呢?

那么,头文件包含什么? - eckes
19个回答

69
我们遇到了这个问题,是因为按照最佳实践进行了CORS设置(例如:http://www.asp.net/web-api/overview/security/enabling-cross-origin-requests-in-web-api),同时在web.config中添加了自定义标头<add name="Access-Control-Allow-Origin" value="*"/>
删除web.config中的该项配置后,问题解决了。
与@mww的答案相反,我们仍然在WebApiConfig.cs中使用了EnableCors(),并且在控制器上使用了EnableCorsAttribute。当我们删除其中一个时,就会遇到其他问题。

13
我移除了这一行代码:<add name="Access-Control-Allow-Origin" value="*"/>,但是我保留了 web.config 文件中的以下两个条目: <add name="Access-Control-Allow-Headers" value="Content-Type" /> <add name="Access-Control-Allow-Methods" value="GET, POST, PUT, DELETE, OPTIONS" /> - Siva Karthikeyan
4
这很关键,你只需启用一次CORS即可。我的问题是我在web.config和app.UseCors()中都启用了它...我删除了web.config的条目,只使用了app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll)方法。 - Mohammad Sepahvand
2
上面那行代码救了我的命!一定要确保不要启用 CORS 超过一次,否则会发生这种情况,让你非常沮丧。 - TGarrett
1
这很关键,你只能启用CORS一次。@MohammadSepahvand谢谢。回到.NET,已经有惊喜了:D。 - Tuan Jinn
当我在配置文件中打开它时,它告诉我有多个头文件。当我在配置文件中关闭它时,它告诉我没有任何头文件。 - PoloHoleSet
显示剩余2条评论

60
我添加了以下内容:

config.EnableCors(new EnableCorsAttribute(Properties.Settings.Default.Cors, "", ""))

以及

app.UseCors(CorsOptions.AllowAll);

在服务器上。这将导致两个标题条目。只需使用后一个即可正常运行。

4
你似乎正在从设置文件中读取 Properties.Settings.Default.Cors。你能发一个例子吗?UseCors 类在哪里? - Hoppe
1
@Hoppe,UseCors是NuGet包Microsoft.Owin.Cors中定义的扩展方法。请参阅http://katanaproject.codeplex.com/SourceControl/latest#src/Microsoft.Owin.Cors/CorsExtensions.cs。 - Papa Mufflon
7
通常在WebApiConfig.cs中调用config.EnableCors(enableCorsAttribute),它是Microsoft.AspNet.WebApi.Cors Nuget包的一部分,使用方法在此处描述:http://www.asp.net/web-api/overview/security/enabling-cross-origin-requests-in-web-api通常在Startup.Auth.cs中作为配置身份提供程序(例如OAuth)的一部分调用app.UseCors(CorsOptions.AllowAll),它是Microsoft.Owin.Cors Nuget包的一部分。 - Henry C
补充一下Papa的回答:你也可以在web.config中设置这个(我在解决其他问题时就是这么做的)。不幸的是,我已经将其添加到WebApiConfig.Register()中,因此出现了双重标头条目。同样的修复方法适用于只在一个地方使用。 - Richard Strickland
我们需要在网站的所有调用中使用CORS,因此从OWINStartup配置中删除了app.UseCors,并解决了问题。 - From Orbonia
显示剩余4条评论

49
我正在使用Cors 5.1.0.0,经过很多麻烦后,我发现问题是由服务器中重复的Access-Control-Allow-Origin和Access-Control-Allow-Header标头引起的。
从WebApiConfig.cs文件中删除config.EnableCors()并仅在控制器类上设置[EnableCors("*","*","*")]属性。
有关更多详细信息,请参阅此文章

1
这对我有效,只需确保您没有在web.config中设置另一个类似于这样的 <add name="Access-Control-Allow-Origin" value="*" />。 - Crismogram

23

添加到注册WebApiConfig

var cors = new EnableCorsAttribute("*", "*", "*");
config.EnableCors(cors);

或者 web.config

<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="*" />
<add name="Access-Control-Allow-Headers" value="Content-Type" />
<add name="Access-Control-Allow-Methods" value="GET, POST, PUT, DELETE, OPTIONS" />
<add name="Access-Control-Allow-Credentials" value="true" />
</customHeaders>  
</httpProtocol>

但不是两者都可以


2
这对我来说是关键的解决方案,不要两者都做。 - robnick
非常感谢提示不要同时设置两个! - LinusGeffarth
1
小心!允许所有来源会带来安全隐患。最好将来源设置为您绝对信任的那些,以避免 CSRF 漏洞。 - GuyPaddock
是的,我同意在生产环境中使用GuyPaddock。 - tfa
没错,这就是正确的解决方案:不要同时使用两个。我有WebApi和MVC;但是由于使用了两个配置文件而发生了冲突。 - benjamingranados

11

Apache服务器:

我花了同样的时间,但原因是我的文件中没有引号(")来提供访问服务器的星号,例如'.htaccess'。

Header add Access-Control-Allow-Origin: * 
Header add Access-Control-Allow-Origin "*" 

你可能在一个文件夹中有一个名为 '.htaccess' 的文件,而这个文件夹的外面还有另一个 '.htaccess' 文件,例如

/ 
- .htaccess 
- public_html / .htaccess (problem here)

对于您的情况,您需要使用IP地址 (http://127.0.0.1:9000) 代替 '*' 来允许服务器提供数据。

ASP.NET:

检查代码中是否存在重复的 'Access-Control-Allow-Origin'。

开发者工具:

使用 Chrome 浏览器可以验证请求头。按 F12 键并转到 '网络' 选项卡,现在运行 AJAX 请求,它将出现在列表中,点击后将显示所有信息。

Access-Control-Allow-Origin: *


有时候,问题就这么简单... 在试图让那些讨厌的 Web 服务在 IIS/Chrome 上运行时,我尝试修改了 Application_BeginRequest 方法,然而却忘记了该方法已经存在于我的代码中!感谢你指出这个显而易见的错误! :) - Juergen Riemer
2
要获取CORS响应头,您还必须模拟实际的跨域请求,因此如果您只查看运行站点上的网络选项卡,则可能不会出现。但是,使用类似DHC(https://chrome.google.com/webstore/detail/dhc-resthttp-api-client/aejoelaoggembcahagimdiliamlcdmfm?hl=en)这样的工具来运行您的AJAX请求将从技术上讲来自不同的域,从而触发CORS并允许您查看Access Control headers 。 - Henry C

11

我也遇到了OWIN和WebAPI都需要单独启用CORS的情况,这反过来导致了'Access-Control-Allow-Origin' header contains multiple values错误。

最后,我删除了所有启用CORS的代码,并在Web.Config文件中的system.webServer节点中添加了以下内容:

<httpProtocol>
  <customHeaders>
    <add name="Access-Control-Allow-Origin" value="https://stethio.azurewebsites.net" />
    <add name="Access-Control-Allow-Methods" value="GET, POST, OPTIONS, PUT, DELETE" />
    <add name="Access-Control-Allow-Headers" value="Origin, X-Requested-With, Content-Type, Accept, Authorization" />
  </customHeaders>
</httpProtocol>

这样做满足了OWIN的CORS要求(允许登录)和WebAPI的要求(允许API调用),但它也带来了一个新问题:我的API调用在预检期间找不到OPTIONS方法。解决办法很简单——我只需要从Web.Config中的handlers节点中删除以下内容:

<remove name="OPTIONSVerbHandler" />

希望这能帮到某人。


9

实际上,你不能设置多个头信息Access-Control-Allow-Origin(或者至少在所有浏览器中都不能生效)。相反,您可以有条件地设置一个环境变量,然后在Header指令中使用它:

SetEnvIf Origin "^(https?://localhost|https://[a-z]+\.my\.base\.domain)$" ORIGIN_SUB_DOMAIN=$1
Header set Access-Control-Allow-Origin: "%{ORIGIN_SUB_DOMAIN}e" env=ORIGIN_SUB_DOMAIN

在这个例子中,如果请求头Origin匹配正则表达式^(https?://localhost|https://[a-z]+\.my\.base\.domain)$(它基本上是指HTTP或HTTPS上的localhost和*.my.base.domain上的HTTPS),则会添加响应头。
记得启用setenvif模块。
文档: 顺便说一下,%{ORIGIN_SUB_DOMAIN}e中的}e并不是笔误,这是在Header指令中使用环境变量的方法。

1
你有没有关于不设置多个访问控制头的来源?我找不到任何证实这一点的东西。 - Spencer
非常聪明和简洁的解决方案。对我起作用了。 - Alex Kalmikov
@Spencer "注意:在实践中,origin-list-or-null生成更受限制。它不是允许由空格分隔的起源列表,而是单个起源或字符串“null”。" http://www.w3.org/TR/cors/#access-control-allow-origin-response-header - Nux

4

如果您在IIS中,需要在web.config中激活CORS,然后您就不需要在App_Start / WebApiConfig.cs Register方法中启用它。

我的解决方案是,在这里注释掉这些行:

// Enable CORS
//EnableCorsAttribute cors = new EnableCorsAttribute("*", "*", "*");
//config.EnableCors(cors);

并在web.config文件中写入:

<system.webServer>
  <httpProtocol>
  <customHeaders>
    <add name="Access-Control-Allow-Origin" value="*" />
  </customHeaders>
</httpProtocol>


4
当您在多个位置配置Cors选项时会出现此问题。在我的情况下,我在控制器级别以及Startup.Auth.cs/ConfigureAuth中都有它。
我的理解是,如果您希望其适用于整个应用程序,则只需像这样在Startup.Auth.cs/ConfigureAuth下进行配置...您需要引用Microsoft.Owin.Cors。
public void ConfigureAuth(IAppBuilder app)
        {
          app.UseCors(CorsOptions.AllowAll);

如果您更愿意将其保留在控制器级别,那么您只需在控制器级别进行插入。

[EnableCors("http://localhost:24589", "*", "*")]
    public class ProductsController : ApiController
    {
        ProductRepository _prodRepo;

在我的情况下,我将其设置在Web.Config和MyAppApiConfig.cs中。从后者中删除它解决了我的问题。 - Jim B

3

我最近在使用Node.js服务器时遇到了这个问题。

以下是我解决问题的方法。
我通过Nginx代理运行我的Node服务器,并设置了Nginx和Node允许跨域请求,但它并不喜欢这样,所以我将其从Nginx中删除,只在Node中保留,然后一切都好了。


谢谢您的回答!它解决了我长时间无法解决的nginx + Rack(Ruby)设置问题。同样的问题,同样的解决方案:关闭nginx中的头部添加,并让rack-cors gem处理CORS问题。轻松解决。 - Pistos
相同的问题。相同的解决方案。谢谢。 - Anurag Bhagsain

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接