在ASP.Net MVC中设置Access-Control-Allow-Origin - 最简单的方法

Kje*_*sen 203 json asp.net-ajax cors asp.net-mvc-3

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

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

Origin http://someothersite.com is not allowed by Access-Control-Allow-Origin.
Run Code Online (Sandbox Code Playgroud)

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

有没有更简单的方法?

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

最佳将是......:

return json(mydata, JsonBehaviour.IDontCareWhoAccessesMe);
Run Code Online (Sandbox Code Playgroud)

jga*_*fin 369

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

创建一个新属性

public class AllowCrossSiteJsonAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        filterContext.RequestContext.HttpContext.Response.AddHeader("Access-Control-Allow-Origin", "*");
        base.OnActionExecuting(filterContext);
    }
}
Run Code Online (Sandbox Code Playgroud)

标记您的行动:

[AllowCrossSiteJson]
public ActionResult YourMethod()
{
    return Json("Works better?");
}
Run Code Online (Sandbox Code Playgroud)

对于ASP.NET Web API

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

标记整个API控制器:

[AllowCrossSiteJson]
public class ValuesController : ApiController
{
Run Code Online (Sandbox Code Playgroud)

或单个API调用:

[AllowCrossSiteJson]
public IEnumerable<PartViewModel> Get()
{
    ...
}
Run Code Online (Sandbox Code Playgroud)

对于Internet Explorer <= v9

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

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

博客文章 | 源代码

  • 我最近将我们的项目更新为MVC 5并试图这样做.即使在过滤器中添加标题似乎也不起作用.当我在网络中查看请求时,响应中不存在标头.还有什么需要做才能让它发挥作用吗? (9认同)
  • 惊人!我luv MVC + U! (8认同)
  • 如果要将CORS限制为您自己的域,则可以轻松扩展属性以接受特定的源. (3认同)
  • 敬畏这个解决方案的优雅 (2认同)
  • 您应该能够将其添加到App_Start\FilterConfig中的RegisterHttpFilters中吗?这样做会将其应用于项目中的所有Api控制器.将此与上面的评论相结合,您可以将CORS限制在所有控制器的域中. (2认同)

Lau*_*att 118

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

<httpProtocol>
   <customHeaders>
      <clear />
      <add name="Access-Control-Allow-Origin" value="*" />
   </customHeaders>
</httpProtocol>
Run Code Online (Sandbox Code Playgroud)

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

  • 此外,这将使整个网站CORS友好.如果有人想仅将单个动作或控制器标记为CORS友好,那么接受的答案要好得多. (29认同)
  • 我认为这比接受的答案更简单. (5认同)

Ken*_*ith 21

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

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

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);
    }
}
Run Code Online (Sandbox Code Playgroud)


Zvo*_*kic 14

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

<system.webServer>
  <httpProtocol>
    <customHeaders>
      <add name="Access-Control-Allow-Origin" value="http://localhost" />
      <add name="Access-Control-Allow-Headers" value="X-AspNet-Version,X-Powered-By,Date,Server,Accept,Accept-Encoding,Accept-Language,Cache-Control,Connection,Content-Length,Content-Type,Host,Origin,Pragma,Referer,User-Agent" />
      <add name="Access-Control-Allow-Methods" value="GET, PUT, POST, DELETE, OPTIONS" />
      <add name="Access-Control-Max-Age" value="1000" />
    </customHeaders>
  </httpProtocol>
</system.webServer>
Run Code Online (Sandbox Code Playgroud)

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

问候 :)


Bis*_*nna 9

有时OPTIONS动词也会导致问题

简单地说:使用以下内容更新web.config

<system.webServer>
    <httpProtocol>
        <customHeaders>
          <add name="Access-Control-Allow-Origin" value="*" />
          <add name="Access-Control-Allow-Headers" value="Origin, X-Requested-With, Content-Type, Accept" />
        </customHeaders>
    </httpProtocol>
</system.webServer>
Run Code Online (Sandbox Code Playgroud)

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

// GET api/Master/Sync/?version=12121
        [HttpGet][HttpOptions]
        public dynamic Sync(string version) 
        {
Run Code Online (Sandbox Code Playgroud)


Tar*_*run 8

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

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


Gop*_*dar 5

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

HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", "*"); 
Run Code Online (Sandbox Code Playgroud)


Gra*_*ush 5

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

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

  2. 在您的WebApiConfig.cs文件中,添加config.EnableCors()到该Register()方法。

  3. 为需要处理 cors 的控制器添加一个属性:

[EnableCors(origins: "<origin address in here>", headers: "*", methods: "*")]


pkm*_*337 5

经过一晚上的努力,我终于成功了。经过一些调试后,我发现我遇到的问题是我的客户端正在发送一个所谓的预检选项请求,以检查是否允许应用程序发送带有提供的来源、方法和标头的发布请求。我不想使用 Owin 或 APIController,因此我开始挖掘并提出了以下仅包含 ActionFilterAttribute 的解决方案。特别是“Access-Control-Allow-Headers”部分非常重要,因为其中提到的标头必须与您的请求将发送的标头匹配。

using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace MyNamespace
{
    public class AllowCrossSiteJsonAttribute : ActionFilterAttribute
    {
        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            HttpRequest request = HttpContext.Current.Request;
            HttpResponse response = HttpContext.Current.Response;

            // check for preflight request
            if (request.Headers.AllKeys.Contains("Origin") && request.HttpMethod == "OPTIONS")
            {
                response.AppendHeader("Access-Control-Allow-Origin", "*");
                response.AppendHeader("Access-Control-Allow-Credentials", "true");
                response.AppendHeader("Access-Control-Allow-Methods", "GET, PUT, POST, DELETE");
                response.AppendHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, X-RequestDigest, Cache-Control, Content-Type, Accept, Access-Control-Allow-Origin, Session, odata-version");
                response.End();
            }
            else
            {
                HttpContext.Current.Response.Cache.SetCacheability(HttpCacheability.NoCache);
                HttpContext.Current.Response.Cache.SetNoStore();

                response.AppendHeader("Access-Control-Allow-Origin", "*");
                response.AppendHeader("Access-Control-Allow-Credentials", "true");
                if (request.HttpMethod == "POST")
                {
                    response.AppendHeader("Access-Control-Allow-Methods", "GET, PUT, POST, DELETE");
                    response.AppendHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, X-RequestDigest, Cache-Control, Content-Type, Accept, Access-Control-Allow-Origin, Session, odata-version");
                }

                base.OnActionExecuting(filterContext);
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

最后,我的 MVC 操作方法如下所示。这里重要的是还要提及 Options HttpVerbs,因为否则预检请求将失败。

[AcceptVerbs(HttpVerbs.Post | HttpVerbs.Options)]
[AllowCrossSiteJson]
public async Task<ActionResult> Create(MyModel model)
{
    return Json(await DoSomething(model));
}
Run Code Online (Sandbox Code Playgroud)