关于json:在ASP.Net MVC中设置Access-Control-Allow-Origin – 最简单的方法

Setting Access-Control-Allow-Origin in ASP.Net MVC - simplest possible method

我有一个简单的actionmethod,返回一些json。 它在ajax.example.com上运行。 我需要从另一个站点someothersite.com访问它。

如果我试着打电话给我,我会得到预期的......:

1
Origin http://someothersite.com is not allowed by Access-Control-Allow-Origin.

我知道有两种解决方法:JSONP和创建自定义HttpHandler
设置标题。

有没有更简单的方法?

简单的动作是否不可能定义允许的起源列表 - 或者简单地允许每个人? 也许一个动作过滤器?

最佳将是......:

1
return json(mydata, JsonBehaviour.IDontCareWhoAccessesMe);


对于普通的ASP.NET MVC控制器

创建一个新属性

1
2
3
4
5
6
7
8
public class AllowCrossSiteJsonAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        filterContext.RequestContext.HttpContext.Response.AddHeader("Access-Control-Allow-Origin","*");
        base.OnActionExecuting(filterContext);
    }
}

标记您的行动:

1
2
3
4
5
[AllowCrossSiteJson]
public ActionResult YourMethod()
{
    return Json("Works better?");
}

对于ASP.NET Web API

1
2
3
4
5
6
7
8
9
10
11
12
13
using System;
using System.Web.Http.Filters;

public class AllowCrossSiteJsonAttribute : ActionFilterAttribute
{
    public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
    {
        if (actionExecutedContext.Response != null)
            actionExecutedContext.Response.Headers.Add("Access-Control-Allow-Origin","*");

        base.OnActionExecuted(actionExecutedContext);
    }
}

标记整个API控制器:

1
2
3
[AllowCrossSiteJson]
public class ValuesController : ApiController
{

或单个API调用:

1
2
3
4
5
[AllowCrossSiteJson]
public IEnumerable<PartViewModel> Get()
{
    ...
}

对于Internet Explorer <= v9

IE <= 9不支持CORS。我写了一个javascript,它会自动通过代理路由这些请求。这一切都是100%透明的(你只需要包含我的代理和脚本)。

使用nuget corsproxy下载并按照附带的说明进行操作。

博客文章|源代码


如果您使用的是IIS 7+,则可以在system.webServer部分中将web.config文件放入该文件夹的根目录中:

1
2
3
4
5
6
<httpProtocol>
   <customHeaders>
      <clear />
     
   </customHeaders>
</httpProtocol>

请参阅:http://msdn.microsoft.com/en-us/library/ms178685.aspx
并且:http://enable-cors.org/#how-iis7


我遇到了一个问题,浏览器拒绝提供它在cookie中传递请求时检索到的内容(例如,xhr的withCredentials=true),并且网站Access-Control-Allow-Origin设置为*。 (Chrome中的错误是"当凭据标志为true时,无法在Access-Control-Allow-Origin中使用通配符。")

基于@jgauffin的答案,我创建了这个,这基本上是一种解决特定浏览器安全检查的方法,因此需要注意。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class AllowCrossSiteJsonAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        // We'd normally just use"*" for the allow-origin header,
        // but Chrome (and perhaps others) won't allow you to use authentication if
        // the header is set to"*".
        // TODO: Check elsewhere to see if the origin is actually on the list of trusted domains.
        var ctx = filterContext.RequestContext.HttpContext;
        var origin = ctx.Request.Headers["Origin"];
        var allowOrigin = !string.IsNullOrWhiteSpace(origin) ? origin :"*";
        ctx.Response.AddHeader("Access-Control-Allow-Origin", allowOrigin);
        ctx.Response.AddHeader("Access-Control-Allow-Headers","*");
        ctx.Response.AddHeader("Access-Control-Allow-Credentials","true");
        base.OnActionExecuting(filterContext);
    }
}

这非常简单,只需在web.config中添加即可

1
2
3
4
5
6
7
8
9
10
<system.webServer>
  <httpProtocol>
    <customHeaders>
     
     
     
     
    </customHeaders>
  </httpProtocol>
</system.webServer>

在Origin中放置了所有可以访问您的Web服务器的域,
在标头中放置任何ajax http请求可以使用的所有可能的标头,
在方法中将您允许的所有方法放在服务器上

问候 :)


WebAPI 2现在有一个CORS包,可以使用以下命令安装:
安装包Microsoft.AspNet.WebApi.Cors -pre -project WebServic

安装完成后,请按照以下代码进行操作:http://www.asp.net/web-api/overview/security/enabling-cross-origin-requests-in-web-api


有时OPTIONS动词也会导致问题

只是:
使用以下内容更新web.config

1
2
3
4
5
6
7
8
<system.webServer>
    <httpProtocol>
        <customHeaders>
         
         
        </customHeaders>
    </httpProtocol>
</system.webServer>

并使用httpGet和httpOptions更新webservice / controller标头

1
2
3
4
// GET api/Master/Sync/?version=12121
        [HttpGet][HttpOptions]
        public dynamic Sync(string version)
        {


本教程非常有用。快速总结一下:

  • 使用Nuget上提供的CORS包:Install-Package Microsoft.AspNet.WebApi.Cors

  • WebApiConfig.cs文件中,将config.EnableCors()添加到Register()方法。

  • 将属性添加到您需要处理cors的控制器:

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


    1
    2
    3
    4
    5
    6
    7
    8
        public ActionResult ActionName(string ReqParam1, string ReqParam2, string ReqParam3, string ReqParam4)
        {
            this.ControllerContext.HttpContext.Response.Headers.Add("Access-Control-Allow-Origin","*");
             /*
                    --Your code goes here --
             */
            return Json(new { ReturnData="Data to be returned", Success=true }, JsonRequestBehavior.AllowGet);
        }

    如果您使用的是API,请将此行添加到您的方法中。

    1
    HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin","*");

    There are different ways we can pass the
    Access-Control-Expose-Headers.

    • 正如jgauffin所解释的那样,我们可以创建一个新属性。
    • 正如LaundroMatt所解释的那样,我们可以添加web.config文件。
    • 另一种方法是我们可以在webApiconfig.cs文件中添加如下代码。

      config.EnableCors(new EnableCorsAttribute(",headers:",methods:"*",exposedHeaders:"TestHeaderToExpose"){SupportsCredentials = true});

    或者我们可以在Global.Asax文件中添加以下代码。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    protected void Application_BeginRequest()
            {
                if (HttpContext.Current.Request.HttpMethod =="OPTIONS")
                {
                    //These headers are handling the"pre-flight" OPTIONS call sent by the browser
                    HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods","GET, POST, OPTIONS");
                    HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers","*");
                    HttpContext.Current.Response.AddHeader("Access-Control-Allow-Credentials","true");
                    HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin","http://localhost:4200");
                    HttpContext.Current.Response.AddHeader("Access-Control-Expose-Headers","TestHeaderToExpose");
                    HttpContext.Current.Response.End();
                }
            }

    我已经为选项编写了它。请根据您的需要进行修改。

    快乐编码!!


    如果你使用IIS,我建议尝试IIS CORS模块。
    它易于配置,适用于所有类型的控制器。

    以下是配置示例:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
        <system.webServer>
            <cors enabled="true" failUnlistedOrigins="true">
               
                <add origin="https://*.microsoft.com"
                     allowCredentials="true"
                     maxAge="120">
                   
                       
                       
                    </allowHeaders>
                   
                         
                    </allowMethods>
                    <exposeHeaders>
                       
                       
                    </exposeHeaders>
                </add>
               
            </cors>
        </system.webServer>


    在Web.config中输入以下内容

    1
    2
    3
    4
    5
    6
    7
    8
    <system.webServer>
    <httpProtocol>
      <customHeaders>
        <clear />    
       
       
      </customHeaders>
    </httpProtocol>