Asp.Net WebApi2启用CORS无法与AspNet.WebApi.Cors 5.2.3一起使用


77

我试图按照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>

任何帮助将非常感激!

谢谢。


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

Answers:


95

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

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

Global.ascx

所有这一切都称为WebApiConfig。只是代码组织而已。

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

WebApiConfig.cs

您这里的关键方法是EnableCrossSiteRequests方法。这就是您需要做的所有事情。该EnableCorsAttribute是一个全球范围的CORS属性

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);
    }
}

价值观控制器

Get方法接收EnableCors我们全局应用的属性。该Another方法将覆盖global 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);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>


19
我跟着从你的答案,从这里所有的步骤:asp.net/web-api/overview/security/...。尝试了各种组合,但除了问题中的Web.config-><customHeaders>东西外,没有启用CORS 。我正在使用最新的软件包(与问题相同)。有什么建议在哪里寻找问题?本质上,由于某种原因,这不能为我解决相同的问题。
yǝsʞǝla

9
“固定它”。由于某种原因,当从Visual Studio运行时,它会在生产环境中(在真正的IIS上)设置CORS标头,而不是在本地主机上设置。我不知道为什么,我想这是有条件的。
yǝsʞǝla

2
在本地IIS上,我有具有不同端口号的单独应用程序。没有Web.Config补丁,Shaun的解决方案就无法工作,直到....我注意到Shaun"*"用于WebApiConfig的起源。因此,我将"*"in作为源添加到控制器的EnableCorsAttribute中,现在它可以在没有WebConfig的情况下使用。我对如何指定Origins的阅读使我相信端口号无效,但是我没有发现“ *”是可以的。同样,大多数示例调用时都config.EnableCors(cors);没有参数。例如:(enable-cors.org/server_aspnet.html
Rob Von

13
在浪费了3个小时尝试使之工作之后,我只是将3个标头添加到了Web配置中,以使其实际工作stackoverflow.com/a/21458845/286121
gyozo kudor

4
@ShaunLuttin我认为我错了,并且确实可以正常工作。似乎框架检查源,并且仅在源位于允许的源列表中时才发送标头。当原点不在列表中时,框架不会发送任何标头(并且我误认为这是错误的行为,因为我希望在标头中看到允许的任何响应的原点)。我将对此进行测试并报告结果。
Aleksei Poliakov

14

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

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>

1
最终我的问题是webconfig
Geomorillo '04 -4-17

1
配置更改对我有用。.我不得不:删除处理程序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 .....这导致它无法工作..根据此答案进行的更改将其修复。谢谢
biso 18'Feb

13

在发生CORS请求的情况下,所有现代浏览器都会使用OPTION动词进行响应,然后再执行实际的请求。如果发生CORS请求,这应该用于提示用户进行确认。但是如果是API,则如果您想跳过此验证过程,请将以下代码段添加到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动词来通过检查。


1
谢谢,http级别的配置不是Microsoft.AspNet.WebApi.Cors依赖项应该处理的内容,因此我们无需在代码中显式配置它?我可以通过在web.config中执行类似的操作来使其工作,但要点是使用Microsoft.AspNet.WebApi.Cors对其进行处理并使其具有属性可配置。
diegosasw 2015年

不知道为什么要完全跳过验证过程。至少不在生产中。如果您想使用设计
好的

1
如果您发现IE在Chrome和Firefox出现故障时仍可正常运行,则很好的解决方案。它在开发环境中对我有用。
2016年

@neeraj在尝试了几十种方法之后,这才使它起作用。它仍然是一种可接受且安全的方法吗?
康妮·德辛科

8

我只是在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
Morvael17年

1
谢谢@Mathter,尽管我通过启动类启用了CORS,但它对我有用。问题是,为什么我们必须在web.config中设置它而不是按常规方式进行设置?
Ciaran Gallagher

4

在对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>

2

这些答案都没有真正起作用。如其他人所述,如果请求具有原始标头,则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);
    }
}

然后在您的Controller动作上使用它:

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

我一般不会保证它的安全性,但是它可能比在web.config中设置标题要安全得多,因为通过这种方式,您可以仅根据需要专门应用它们。

当然,修改上述内容以仅允许某些来源,方法等很简单。


不要认为这在Visual Studio调试情况下有效。似乎甚至没有达到该代码,因为Visual Studio的IIS甚至在此代码之前就占用了请求。
瑞安

1

我刚刚遇到了同样的问题,试图在全球范围内启用CORS。但是我发现它确实起作用,但是仅当请求包含Origin标头值时才起作用。如果您省略origin标头值,则响应将不包含Access-Control-Allow-Origin

我使用了一个称为DHC的Chrome插件来测试我的GET请求。它使我可以Origin轻松添加标题。


1

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

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

在解决方案资源管理器中,右键单击api-project。在属性窗口中设置“匿名身份验证”,以启用

希望这对以后的人有所帮助。


configglobal.asax.cs中没有任何内容。
tala9999

应该是WebApiConfig.cs,位于Register()中
HomeMade '19

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中全局使用它,它才起作用。使用此解决方案最终对于每个控制器对我而言都是有效的。谢谢。
tno2007 '19

0

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

如果所有OPTIONS请求导致您遇到问题,则基本上将它们设置为忽略路由:

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

详细信息:停止Web API处理OPTIONS请求


0

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

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

并且收到有关原点的错误,不能为null或空字符串。但是该错误发生在所有位置的Global.asax.cs文件中。解决方案是将其更改为:

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

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

希望这对某人有帮助。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.