【问题标题】:MVC web api: No 'Access-Control-Allow-Origin' header is present on the requested resourceMVC web api:请求的资源上不存在“Access-Control-Allow-Origin”标头
【发布时间】:2015-02-14 17:48:33
【问题描述】:

我尝试了这篇文章中写的所有内容:http://www.asp.net/web-api/overview/security/enabling-cross-origin-requests-in-web-api,但没有任何效果。 我正在尝试使用 angularJS 从 webAPI2 (MVC5) 获取数据以在另一个域中使用。

我的控制器如下所示:

namespace tapuzWebAPI.Controllers
{
    [EnableCors(origins: "http://local.tapuz.co.il", headers: "*", methods: "*", SupportsCredentials = true)]
    [RoutePrefix("api/homepage")]
    public class HomePageController : ApiController
    {
        [HttpGet]
        [Route("GetMainItems")]
        //[ResponseType(typeof(Product))]
        public List<usp_MobileSelectTopSecondaryItemsByCategoryResult> GetMainItems()
        {


            HomePageDALcs dal = new HomePageDALcs();
            //Three product added to display the data

            //HomePagePromotedItems.Value.Add(new HomePagePromotedItem.Value.FirstOrDefault((p) => p.ID == id));


            List<usp_MobileSelectTopSecondaryItemsByCategoryResult> items = dal.MobileSelectTopSecondaryItemsByCategory(3, 5);
            return items;

        }      
    }
}

【问题讨论】:

  • 也分享您的角度代码以请求 cors
  • 他的角度代码可能没有问题,因为大多数 CORS 问题只是因为服务器配置
  • 我有同样的设置,我注意到当我在 API 上请求一个不存在的操作时,WebApi 返回一个 404,CORS 标头丢失并且浏览器会抱怨。所以,也许就这么简单。

标签: c# asp.net-mvc angularjs asp.net-web-api cors


【解决方案1】:

您需要在 Web Api 中启用 CORS。全局启用 CORS 的更简单且首选的方法是将以下内容添加到 web.config

<system.webServer>
  <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" />
    </customHeaders>
  </httpProtocol>
</system.webServer>

请注意,方法都是单独指定的,而不是使用*。这是因为使用*时出现了一个bug。

您也可以通过代码启用CORS

更新
需要以下 NuGet 包:Microsoft.AspNet.WebApi.Cors

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        config.EnableCors();

        // ...
    }
}

然后你可以像这样在 Actions 或 Controllers 上使用[EnableCors] 属性

[EnableCors(origins: "http://www.example.com", headers: "*", methods: "*")]

也可以全局注册

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        var cors = new EnableCorsAttribute("http://www.example.com", "*", "*");
        config.EnableCors(cors);

        // ...
    }
}

您还需要使用HTTP OPTIONS 请求处理预检Options 请求

Web API 需要响应Options 请求,以确认它确实配置为支持CORS

要处理这个问题,您需要做的就是发回一个空响应。您可以在您的操作中执行此操作,也可以像这样在全局范围内执行此操作:

# Global.asax.cs
protected void Application_BeginRequest()
{
    if (Request.Headers.AllKeys.Contains("Origin") && Request.HttpMethod == "OPTIONS")
    {
        Response.Flush();
    }
}

添加了这个额外的检查以确保旧的APIs 设计为只接受GETPOST 请求不会被利用。想象一下,当这个 动词 不存在时,向 API 发送一个 DELETE 请求。结果是不可预测的,结果可能是危险的

【讨论】:

  • 您的回答帮助了我。我已经用代码库解决方案尽我所能。在阅读您的答案之前,我没有尝试使用 web.config 选项。这是唯一一个有效的。知道为什么吗?我将 Web API 2 与 OData 一起使用。不管怎么说,还是要谢谢你! :)
  • 供将来参考,您需要的 NuGet 包是“Microsoft.AspNet.WebApi.Cors”。
  • 我已经按照你的所有回答,我有两个问题: Application_BeginRequest() 应该在哪里被调用?其次,在同样的方法中,.Contains("Origin") 并没有真正在我身上编译,这个方法是从哪里来的,String.Contains 还是 Linq.Contains?
  • 记住不同的端口#构成不同的域,这可能是一个陷阱。 foo.com 是不同的域 与 foo.com:8080
  • 你救了我的命;)
【解决方案2】:

@Mihai-Andrei Dinculescu 的回答是正确的,但是为了搜索者的利益,还有一个微妙的地方会导致这个错误。

在您的 URL 末尾添加一个“/”将阻止 EnableCors 在所有情况下(例如从主页)工作。

即这行不通

var cors = new EnableCorsAttribute("http://testing.azurewebsites.net/", "*", "*");
config.EnableCors(cors);

但这会起作用:

var cors = new EnableCorsAttribute("http://testing.azurewebsites.net", "*", "*");
config.EnableCors(cors);

如果使用 EnableCors 属性,效果是一样的。

【讨论】:

  • 谢谢!!这很有帮助。
【解决方案3】:

我按照 Mihai-Andrei Dinculescu 指示的上述所有步骤进行操作。
但就我而言,我还需要 1 个 步骤,因为 http OPTIONS 在 Web.Config 中被下面的行禁用了。

&lt;remove name="OPTIONSVerbHandler" /&gt;

我刚刚从 Web.Config 中删除了它(只需在下面评论它),Cors 就像一个魅力

<handlers>
  <!-- remove name="OPTIONSVerbHandler" / -->
</handlers>

【讨论】:

    【解决方案4】:

    可能是因为安装了 Cors nuget 包。

    如果您在从 nuget 安装和启用 cors 后遇到问题,那么您可以尝试重新安装 web Api。

    在包管理器中,运行Update-Package Microsoft.AspNet.WebApi -reinstall

    【讨论】:

    • 这正是适合我的。我安装了 System.Web.Http.Cors 然后卸载了,这使得 WebApi 在 5.2.2 和 5.2.3 之间的错误(新升级)版本
    • 很高兴我在最初设置 cors 时看到了这一点。后来,我卸载了一个与 cors 无关的包,导致 WebAPI cors 处于不良状态。
    【解决方案5】:

    试试这个,确保你正确配置了 CORS:

    [EnableCors(origins: "*", headers: "*", methods: "*")]
    

    还是不行?检查 HTTP 标头是否存在。

    【讨论】:

    • 检查它是否工作,最好删除supportCredentials,它确实在某些情况下禁用cors
    • 最佳答案,因为我不想为我的整个站点启用 CORS,只为某些端点启用。这也需要config.EnableCors()
    【解决方案6】:

    我知道我来得太晚了。但是,对于任何正在搜索的人,我想我会发布最终对我有用的东西。我并不是说它是最好的解决方案——只是它有效。

    我们的 WebApi 服务使用 config.EnableCors(corsAttribute) 方法。但是,即使这样,它仍然会在飞行前请求上失败。 @Mihai-Andrei Dinculescu 的回答为我提供了线索。首先,我添加了他的 Application_BeginRequest() 代码来刷新选项请求。那仍然对我不起作用。问题是 WebAPI 仍然没有向 OPTIONS 请求添加任何预期的标头。单独冲洗它不起作用 - 但它给了我一个想法。我添加了自定义标头,否则这些标头将通过 web.config 添加到 OPTIONS 请求的响应中。这是我的代码:

    protected void Application_BeginRequest()
    {
      if (Request.Headers.AllKeys.Contains("Origin") && Request.HttpMethod == "OPTIONS")
      {
        Response.Headers.Add("Access-Control-Allow-Origin", "https://localhost:44343");
        Response.Headers.Add("Access-Control-Allow-Headers",
          "Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With");
        Response.Headers.Add("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
        Response.Headers.Add("Access-Control-Allow-Credentials", "true");
        Response.Flush();
      }
    }
    

    显然,这仅适用于 OPTIONS 请求。所有其他动词都由 CORS 配置处理。如果有更好的方法来解决这个问题,我会全力以赴。对我来说,这感觉像是作弊,如果标题是自动添加的,我更愿意,但这最终奏效了,让我继续前进。

    【讨论】:

    • 你迟到了,但这通过将这些作为 http 标头添加到 Web 配置中帮助我解决了遗留问题。谢谢
    【解决方案7】:

    要使任何 CORS 协议正常工作,您需要在每个端点上都有一个 OPTIONS 方法(或使用此方法的全局过滤器),它将返回这些标头:

    Access-Control-Allow-Origin: *
    Access-Control-Allow-Methods: GET, POST, PUT, DELETE
    Access-Control-Allow-Headers: content-type
    

    原因是浏览器将首先发送一个 OPTIONS 请求来“测试”您的服务器并查看授权

    【讨论】:

      【解决方案8】:

      我发现了下一个关于 cors 的案例。也许它对某人有用。 如果您向服务器添加功能“WebDav Redirector”,则 PUT 和 DELETE 请求将失败。

      因此,您需要从 IIS 服务器中删除“WebDAVModule”:

      • “在 IIS 模块配置中,循环 WebDAVModule,如果您的 Web 服务器有,则将其删除”。

      或添加到您的配置中:

      <system.webServer>
      <modules>
        <remove name="WebDAVModule"/>
      </modules>
      <handlers>
        <remove name="WebDAV" />
        ...
      </handlers>
      

      【讨论】:

        【解决方案9】:

        当您尝试从不同的域或不同的端口访问时会出现此问题。

        如果您使用的是 Visual Studio,请转到工具 > NuGet 包管理器 > 包管理器控制台。在那里你必须安装 NuGet 包Microsoft.AspNet.WebApi.Cors

        Install-Package Microsoft.AspNet.WebApi.Cors
        

        然后,在 PROJECT > App_Start > WebApiConfig 中,启用 CORS

        public static class WebApiConfig
        {
            public static void Register(HttpConfiguration config)
            {
                
                //Enable CORS. Note that the domain doesn't have / in the end.
                config.EnableCors(new EnableCorsAttribute("https://tiagoperes.eu",headers:"*",methods:"*"));
        
                ....
        
            }
        }
        

        一旦安装成功,构建解决方案就足够了

        【讨论】:

          【解决方案10】:

          @Mihai-Andrei Dinculescu 的回答对我有用,例如:

          • 在 web.config 的 &lt;system.webServer&gt; 部分中添加 &lt;httpProtocol&gt;
          • 通过global.asax 中提到的Application_BeginRequest()OPTIONS 请求返回空响应

          除了他对Request.Headers.AllKeys.Contains("Origin") 的检查对我不起作用,因为请求包含origing,所以是小写的。我认为我的浏览器(Chrome)会这样发送 CORS 请求。

          我通过使用a case insensitive 他的Contains 检查的变体来更通用地解决了这个问题: if (culture.CompareInfo.IndexOf(string.Join(",", Request.Headers.AllKeys), "Origin", CompareOptions.IgnoreCase) >= 0) {

          【讨论】:

            【解决方案11】:

            如果您的 web.config 中有 security\requestFiltering 节点,如下所示:

            <security>
              <requestFiltering>
                <verbs allowUnlisted="false">
                  <add verb="GET" allowed="true" />
                  <add verb="POST" allowed="true" />
                  <add verb="PUT" allowed="true" />
                  <add verb="DELETE" allowed="true" />
                  <add verb="DEBUG" allowed="true" />          
                </verbs>
              </requestFiltering>
            

            确保你也添加了这个

            <add verb="OPTIONS" allowed="true" />
            

            【讨论】:

              【解决方案12】:

              我已经尝试了我在网上可以找到的所有东西,包括在这个答案中给出的方法。 在几乎一整天都在尝试解决这个问题之后,我找到了对我有用的解决方案。

              App_Start文件夹的WebApiConfig文件中,注释所有代码行并添加以下代码:

              `public static void Register(HttpConfiguration config)
                  {
                      // Web API configuration and services
                      config.EnableCors();
                      var enableCorsAttribute = new EnableCorsAttribute("*",
                                                         "Origin, Content-Type, Accept",
                                                         "GET, PUT, POST, DELETE, OPTIONS");
                      config.EnableCors(enableCorsAttribute);
                      // Web API routes
                      config.MapHttpAttributeRoutes();
              
                      config.Routes.MapHttpRoute(
                          name: "DefaultApi",
                          //routeTemplate: "api/{controller}/{id}",
                          routeTemplate: "api/{controller}/{action}/{id}",
                          defaults: new { id = RouteParameter.Optional }
                      );
                      config.Formatters.Add(new BrowserJsonFormatter());
                  }
              
                  public class BrowserJsonFormatter : JsonMediaTypeFormatter
                  {
                      public BrowserJsonFormatter()
                      {
                          this.SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/html"));
                          this.SerializerSettings.Formatting = Formatting.Indented;
                      }
              
                      public override void SetDefaultContentHeaders(Type type, HttpContentHeaders headers, MediaTypeHeaderValue mediaType)
                      {
                          base.SetDefaultContentHeaders(type, headers, mediaType);
                          headers.ContentType = new MediaTypeHeaderValue("application/json");
                      }
                  }`
              

              【讨论】:

                【解决方案13】:

                我知道人们一开始可能会觉得这很明显,但请认真考虑一下。如果您做错了什么,这通常会发生。

                例如,我遇到了这个问题,因为我没有在我的主机文件中添加主机条目。真正的问题是 DNS 解析。或者我只是把基本 URL 弄错了。

                如果身份令牌来自一台服务器,有时我会收到此错误,但我正尝试在另一台服务器上使用它。

                如果资源错误,有时会出现此错误。

                如果您将 CORS 中间件放在链中太晚,您可能会遇到这种情况。

                【讨论】:

                  【解决方案14】:

                  避免在多个地方启用 CORS,如 WebApiCONfig.cs、提供程序中的 GrantResourceOwnerCredentials 方法和 Controller Header 属性等。 以下是导致访问控制允许来源的列表

                  1. Web 无法与您使用的 DB 交互。
                  2. AWS Cloud 如果 Web API 和 DB 的 VPC 不同。

                  以下代码足以修复访问控制允许来源。 //确保 app.UseCors 应该位于配置代码行的顶部。

                     public partial class Startup
                      {
                          public void Configuration(IAppBuilder app)
                          {
                              app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
                              //All other configurations
                          }
                      }
                  

                  这减缓了我的问题。

                  【讨论】:

                    【解决方案15】:

                    安装包:Microsoft.AspNet.WebApi.Cors

                    转到:App_Start --> WebApiConfig

                    添加:

                    var cors = new EnableCorsAttribute("http://localhost:4200", "", ""); config.EnableCors(cors);

                    注意:如果您将“/”作为特定网址的结尾添加,则对我不起作用。

                    【讨论】:

                      【解决方案16】:

                      对于只是在 .NET 5 中创建 Web API 而不是 Web 应用程序的人,您需要在 Startup.cs 中配置您的策略,如下所示:

                      public void ConfigureServices(IServiceCollection services)
                      {
                          // Additional configs above...
                          services.AddCors(options =>
                          {
                              options.AddPolicy("AllowAnyOrigin", builder =>
                              {
                                  // Allow "Access-Control-Allow-Origin: *" header
                                  builder.AllowAnyOrigin();
                              });
                          });
                      }
                      
                      public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
                      {
                          // Add this above other config options...
                          app.UseCors("AllowAnyOrigin");
                      }
                      

                      【讨论】:

                      • .AllowAnyOrigin() 不会导致跨站请求伪造?
                      【解决方案17】:

                      我知道这听起来很疯狂,但对我来说是 [HttpPost()] 而不是 [HttpPost]。当我删除多余的括号时,它开始工作了

                      【讨论】:

                        猜你喜欢
                        • 2020-11-06
                        • 1970-01-01
                        • 1970-01-01
                        • 2013-11-29
                        • 2014-07-28
                        • 2014-01-19
                        相关资源
                        最近更新 更多