【问题标题】:Asp.Net WebApi2 Enable CORS not working with AspNet.WebApi.Cors 5.2.3Asp.Net WebApi2 启用 CORS 不适用于 AspNet.WebApi.Cors 5.2.3
【发布时间】:2015-05-15 11:13:24
【问题描述】:

我尝试按照http://enable-cors.org/server_aspnet.html 的步骤进行操作 让我的 RESTful API(用 ASP.NET WebAPI2 实现)处理跨源请求(启用 CORS)。除非我修改 web.config,否则它不起作用。

我安装了 WebApi Cors 依赖:

install-package Microsoft.AspNet.WebApi.Cors -ProjectName MyProject.Web.Api

然后在我的App_Start 中,我的课程WebApiConfig 如下:

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        var corsAttr = new EnableCorsAttribute("*", "*", "*");
        config.EnableCors(corsAttr);

        var constraintsResolver = new DefaultInlineConstraintResolver();

        constraintsResolver.ConstraintMap.Add("apiVersionConstraint", typeof(ApiVersionConstraint));
        config.MapHttpAttributeRoutes(constraintsResolver); 
        config.Services.Replace(typeof(IHttpControllerSelector), new NamespaceHttpControllerSelector(config));
        //config.EnableSystemDiagnosticsTracing(); 
        config.Services.Replace(typeof(ITraceWriter), new SimpleTraceWriter(WebContainerManager.Get<ILogManager>())); 
        config.Services.Add(typeof(IExceptionLogger), new SimpleExceptionLogger(WebContainerManager.Get<ILogManager>()));
        config.Services.Replace(typeof(IExceptionHandler), new GlobalExceptionHandler()); 
    }
}

但在运行应用程序之后,我向 Fiddler 请求资源,例如: http://localhost:51589/api/v1/persons 在响应中,我看不到应该看到的 HTTP 标头,例如:

  • Access-Control-Allow-Methods: POST, PUT, DELETE, GET, OPTIONS
  • Access-Control-Allow-Origin: *

我错过了一些步骤吗?我已经尝试在控制器上使用以下注释:

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

结果相同,没有启用 CORS。

但是,如果我在 web.config 中添加以下内容(甚至没有安装 AspNet.WebApi.Cors 依赖项),它就可以工作:

<system.webServer>

<httpProtocol>
  <!-- THESE HEADERS ARE IMPORTANT TO WORK WITH CORS -->
  <!--
  <customHeaders>
    <add name="Access-Control-Allow-Origin" value="*" />
    <add name="Access-Control-Allow-Methods" value="POST, PUT, DELETE, GET, OPTIONS" />
    <add name="Access-Control-Allow-Headers" value="content-Type, accept, origin, X-Requested-With, Authorization, name" />
    <add name="Access-Control-Allow-Credentials" value="true" />
  </customHeaders>
  -->
</httpProtocol>
<handlers>
  <!-- THESE HANDLERS ARE IMPORTANT FOR WEB API TO WORK WITH  GET,HEAD,POST,PUT,DELETE and CORS-->
  <!--

  <remove name="WebDAV" />
  <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="GET,HEAD,POST,PUT,DELETE" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
  <remove name="ExtensionlessUrlHandler-Integrated-4.0" />
  <remove name="OPTIONSVerbHandler" />
  <remove name="TRACEVerbHandler" />
  <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
-->
</handlers>

任何帮助将不胜感激!

谢谢。

【问题讨论】:

  • 我遇到了同样的问题,但我决定直接在控制器中设置 Access-Control-Allow-Origin 标头: HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.OK); //如果需要,添加一些检查 response.Headers.Add("Access-Control-Allow-Origin", "*");

标签: c# rest cors asp.net-web-api2


【解决方案1】:

没有一个安全的解决方案对我有用,所以比 Neeraj 更安全,比 Matthew 更容易,只需添加: System.Web.HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", "*");

在控制器的方法中。这对我有用。

public IHttpActionResult Get()
{
    System.Web.HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", "*");
    return Ok("value");
}

【讨论】:

  • 我使用了 CORS 库并将属性放在控制器上,但它不起作用。仅在 WebApiConfig 中全局使用它确实有效。使用此解决方案最终对我每个控制器都有效。谢谢。
【解决方案2】:

我已经为您创建了一个精简的演示项目。

您可以从本地 Fiddler 尝试上述 API 链接 来查看标头。这是一个解释。

Global.ascx

所有这一切都是调用WebApiConfig。只不过是代码组织。

public class WebApiApplication : System.Web.HttpApplication
{
    protected void Application_Start()
    {
        WebApiConfig.Register(GlobalConfiguration.Configuration);
    }
}

WebApiConfig.cs

这里的关键方法是EnableCrossSiteRequests 方法。这是您需要做的全部EnableCorsAttributeglobally scoped CORS attribute

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        EnableCrossSiteRequests(config);
        AddRoutes(config);
    }

    private static void AddRoutes(HttpConfiguration config)
    {
        config.Routes.MapHttpRoute(
            name: "Default",
            routeTemplate: "api/{controller}/"
        );
    }

    private static void EnableCrossSiteRequests(HttpConfiguration config)
    {
        var cors = new EnableCorsAttribute(
            origins: "*", 
            headers: "*", 
            methods: "*");
        config.EnableCors(cors);
    }
}

Values Controller

Get 方法接收我们全局应用的EnableCors 属性。 Another 方法会覆盖全局 EnableCors

public class ValuesController : ApiController
{
    // GET api/values
    public IEnumerable<string> Get()
    {
        return new string[] { 
            "This is a CORS response.", 
            "It works from any origin." 
        };
    }

    // GET api/values/another
    [HttpGet]
    [EnableCors(origins:"http://www.bigfont.ca", headers:"*", methods: "*")]
    public IEnumerable<string> Another()
    {
        return new string[] { 
            "This is a CORS response. ", 
            "It works only from two origins: ",
            "1. www.bigfont.ca ",
            "2. the same origin." 
        };
    }
}

Web.config

您不需要在 web.config 中添加任何特殊内容。事实上,这就是演示的 web.config 的样子——它是空的。

<?xml version="1.0" encoding="utf-8"?>
<configuration>
</configuration>

演示

var url = "https://cors-webapi.azurewebsites.net/api/values"

$.get(url, function(data) {
  console.log("We expect this to succeed.");
  console.log(data);
});

var url = "https://cors-webapi.azurewebsites.net/api/values/another"

$.get(url, function(data) {
  console.log(data);
}).fail(function(xhr, status, text) {
  console.log("We expect this to fail.");
  console.log(status);
});
&lt;script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"&gt;&lt;/script&gt;

【讨论】:

  • 我按照您的回答和此处的所有步骤操作:asp.net/web-api/overview/security/…。尝试了各种组合,除了问题中的 Web.config->&lt;customHeaders&gt; 之外,没有任何东西可以启用 CORS。我正在使用最新的软件包(与问题相同)。有什么建议可以在哪里寻找问题?本质上,出于某种原因,这并不能为我解决同样的问题。
  • “已修复”。出于某种原因,它在生产中(在真正的 IIS 上)设置 CORS 标头,但在从 VisualStudio 运行时不在本地主机上。我不知道为什么,我猜它是有条件的。
  • 在我的本地 IIS 上,我有具有不同端口号的单独应用程序。在没有 Web.Config 补丁之前,Shaun 的解决方案无法工作,直到......我注意到 Shaun 使用 "*" 作为 WebApiConfig 中的来源。所以我把"*" 作为控制器中EnableCorsAttribute 的原点,现在它在没有WebConfig 的情况下工作。我对如何指定 Origins 的阅读使我相信端口号无效,但我没有发现“*”是可以的。此外,大多数示例在没有参数的情况下调用 config.EnableCors(cors);。例如:(enable-cors.org/server_aspnet.html)
  • 在浪费了 3 个小时试图让它工作之后,我只是将 3 个标头添加到 Web 配置中以实际让它工作stackoverflow.com/a/21458845/286121
  • @ShaunLuttin 我想我错了,它确实有效。似乎框架仅在来源位于允许的来源列表中时才检查来源并发送标头。当来源不在列表中时,框架不发送标头(我错误地将其解释为错误行为,因为我希望在任何响应的标头中看到允许的来源)。我将对此进行测试并报告结果。
【解决方案3】:

在对我的 Web.config CORS 进行一些修改后,我的 Web API 2 项目中突然停止工作(至少对于预检期间的 OPTIONS 请求)。看来您需要在 Web.config 中包含下面提到的部分,否则(全局)EnableCorsAttribute 将不适用于 OPTIONS 请求。请注意,这与 Visual Studio 将在新的 Web API 2 项目中添加的部分完全相同。

<system.webServer>
  <handlers>
    <remove name="ExtensionlessUrlHandler-Integrated-4.0"/>
    <remove name="OPTIONSVerbHandler"/>
    <remove name="TRACEVerbHandler"/>
    <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0"/>
  </handlers>
</system.webServer>

【讨论】:

    【解决方案4】:

    WEBAPI2:解决方案。 global.asax.cs:

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

    在解决方案资源管理器中,右键单击 api-project。在 属性窗口将 'Anonymous Authentication' 设置为 Enabled !!!

    希望这对将来的某人有所帮助。

    【讨论】:

    • global.asax.cs 中没有config
    • 应该是WebApiConfig.cs,在Register()里面
    【解决方案5】:

    我刚刚在 Web.config 中添加了自定义标头,它就像一个魅力。

    关于配置 - system.webServer:

    <httpProtocol>
      <customHeaders>
        <add name="Access-Control-Allow-Origin" value="*" />
        <add name="Access-Control-Allow-Headers" value="Content-Type" />
      </customHeaders>
    </httpProtocol>
    

    我的前端应用和后端在同一个解决方案上。为此,我需要将 Web 服务项目(后端)设置为默认设置。

    我正在使用 ReST,没有尝试过其他任何东西。

    【讨论】:

    • 正如其他人所说,浪费时间试图让它“正常”工作,然后把它推到 web.config 中
    • 谢谢@Mathter,这对我有用,尽管通过我的启动课程启用了 CORS。问题是,为什么我们必须在 web.config 中设置它而不是常规方式?
    【解决方案6】:

    您只需要更改一些文件。这对我有用。

    Global.ascx

    public class WebApiApplication : System.Web.HttpApplication {
        protected void Application_Start()
        {
            WebApiConfig.Register(GlobalConfiguration.Configuration);
        } }
    

    WebApiConfig.cs

    所有的请求都必须调用这个代码。

    public static class WebApiConfig {
        public static void Register(HttpConfiguration config)
        {
            EnableCrossSiteRequests(config);
            AddRoutes(config);
        }
    
        private static void AddRoutes(HttpConfiguration config)
        {
            config.Routes.MapHttpRoute(
                name: "Default",
                routeTemplate: "api/{controller}/"
            );
        }
    
        private static void EnableCrossSiteRequests(HttpConfiguration config)
        {
            var cors = new EnableCorsAttribute(
                origins: "*", 
                headers: "*", 
                methods: "*");
            config.EnableCors(cors);
        } }
    

    某些控制器

    没什么可改变的。

    Web.config

    您需要在 web.config 中添加处理程序

    <configuration> 
      <system.webServer>
        <handlers>
          <remove name="ExtensionlessUrlHandler-Integrated-4.0" />
          <remove name="OPTIONSVerbHandler" />
          <remove name="TRACEVerbHandler" />
          <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
        </handlers>   
      </system.webServer> 
    </configuration>
    

    【讨论】:

    • 最后我的问题是 webconfig
    • 配置更改对我有用.. 我有:删除处理程序 ExtensionlessUrlHandler-ISAPI-4.0_32bit ExtensionlessUrlHandler-ISAPI-4.0_64bit ExtensionlessUrlHandler-Integrated-4.0 WebDAV 并添加处理程序 ExtensionlessUrlHandler-ISAPI-4.0_32bit ExtensionlessUrlHandler-ISAPI-4.0_64bit ExtensionlessUrlHandler-Integrated-4.0 .....这导致它不起作用..根据这个答案的更改修复了它。谢谢
    【解决方案7】:

    希望这对将来的某人有所帮助。我的问题是我遵循与 OP 相同的教程来启用全局 CORS。但是,我还在我的 AccountController.cs 文件中设置了特定于操作的 CORS 规则:

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

    并且收到关于来源的错误,不能为 null 或空字符串。但是错误发生在所有地方的 Global.asax.cs 文件中。解决办法是改成:

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

    注意到起源中的 * 了吗?缺少那是导致 Global.asax.cs 文件中的错误的原因。

    希望这对某人有所帮助。

    【讨论】:

      【解决方案8】:

      我发现这个问题是因为我遇到了大多数浏览器发送的 OPTIONS 请求的问题。我的应用程序正在路由 OPTIONS 请求并使用我的 IoC 构造大量对象,其中一些由于各种原因在这种奇怪的请求类型上抛出异常。

      如果所有 OPTIONS 请求给您带来问题,则基本上为它们设置一个忽略路由:

      var constraints = new { httpMethod = new HttpMethodConstraint(HttpMethod.Options) };
      config.Routes.IgnoreRoute("OPTIONS", "{*pathInfo}", constraints);
      

      更多信息:Stop Web API processing OPTIONS requests

      【讨论】:

        【解决方案9】:

        这些答案都不起作用。正如其他人指出的那样,如果请求具有 Origin 标头,Cors 包将仅使用 Access-Control-Allow-Origin 标头。但是通常不能只在请求中添加一个 Origin 标头,因为浏览器也可能会尝试对其进行规范。

        如果您想要一种快速而肮脏的方式来允许对 Web api 的跨站点请求,那么编写一个自定义过滤器属性真的要容易得多:

        public class AllowCors : ActionFilterAttribute
        {
            public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
            {
                if (actionExecutedContext == null)
                {
                    throw new ArgumentNullException("actionExecutedContext");
                }
                else
                {
                    actionExecutedContext.Response.Headers.Remove("Access-Control-Allow-Origin");
                    actionExecutedContext.Response.Headers.Add("Access-Control-Allow-Origin", "*");
                }
                base.OnActionExecuted(actionExecutedContext);
            }
        }
        

        然后在你的控制器动作中使用它:

        [AllowCors]
        public IHttpActionResult Get()
        {
            return Ok("value");
        }
        

        我一般不会保证它的安全性,但它可能比在 web.config 中设置标头更安全,因为这样您可以只在需要时应用它们。

        当然,修改上面的内容很简单,只允许某些来源、方法等。

        【讨论】:

        • 不要认为这在 Visual Studio 调试情况下有效。似乎甚至没有到达此代码,因为 Visual Studio 的 IIS 甚至在此代码之前吃掉了请求。
        【解决方案10】:

        我刚遇到同样的问题,尝试enable CORS globally。但是我发现它 确实 工作,但是只有当请求包含 Origin 标头值时。如果省略 origin 标头值,则响应将不包含 Access-Control-Allow-Origin

        我使用了一个名为 DHC 的 chrome 插件来测试我的 GET 请求。它让我可以轻松添加 Origin 标头。

        【讨论】:

          【解决方案11】:

          在 CORS 请求的情况下,所有现代浏览器都会以 OPTION 动词进行响应,然后实际的请求会继续执行。这应该用于在 CORS 请求的情况下提示用户进行确认。但是对于 API,如果您想跳过此验证过程,请将以下 sn-p 添加到 Global.asax

                  protected void Application_BeginRequest(object sender, EventArgs e)
                  {
                      HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", "*");
                      if (HttpContext.Current.Request.HttpMethod == "OPTIONS")
                      {
                          HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods", "POST, PUT, DELETE");
          
                          HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers", "Content-Type, Accept");
                          HttpContext.Current.Response.AddHeader("Access-Control-Max-Age", "1728000");
                          HttpContext.Current.Response.End();
                      }
                  }
          

          这里我们只是通过检查 OPTIONS 动词来通过检查。

          【讨论】:

          • 谢谢,这个http级别的配置不就是依赖Microsoft.AspNet.WebApi.Cors应该处理的,所以我们不需要在我们的代码中显式配置它吗?我可以通过在 web.config 中执行类似的操作来让它工作,但重点是使用 Microsoft.AspNet.WebApi.Cors 来处理它并使其属性可配置。
          • 不确定您为什么要完全跳过验证过程。至少不在生产中。如果您想按照设计使用内置的东西,您可以正确配置 CORS,然后忽略 OPTIONS 请求的路由,如我的回答中所述
          • 如果您发现 IE 可以在 Chrome 和 Firefox 失败的情况下运行,这很可能是解决方案。它在开发环境中对我有用。
          • @neeraj 在尝试了几十种方法之后,这是唯一使它起作用的方法。它仍然是一种可接受且安全的方法吗?
          猜你喜欢
          • 2017-07-06
          • 2015-02-21
          • 2019-12-23
          • 2017-01-09
          • 2019-10-22
          • 2017-11-06
          • 2015-06-27
          • 2018-05-29
          相关资源
          最近更新 更多