在ASP.Net MVC中设置访问控制允许来源-最简单的方法


206

我有一个简单的操作方法,它返回一些json。它在ajax.example.com上运行。我需要从另一个网站someothersite.com访问此网站。

如果我尝试调用它,我会得到预期的...:

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

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

有没有更简单的方法?

简单的动作是否不可能定义允许的来源列表-还是简单地允许所有人?也许是动作筛选器?

最佳将是...:

return json(mydata, JsonBehaviour.IDontCareWhoAccessesMe);

1
请在此处查看vNext和MVC6:neelbhatt40.wordpress.com/2015/09/10/…–
Neel

Answers:


381

对于纯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);
    }
}

标记您的动作:

[AllowCrossSiteJson]
public ActionResult YourMethod()
{
    return Json("Works better?");
}

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

标记整个API控制器:

[AllowCrossSiteJson]
public class ValuesController : ApiController
{

或单独的API调用:

[AllowCrossSiteJson]
public IEnumerable<PartViewModel> Get()
{
    ...
}

对于Internet Explorer <= v9

IE <= 9不支持CORS。我已经编写了一个JavaScript,它将通过代理自动路由这些请求。所有这些都是100%透明的(您只需要包括我的代理和脚本即可)。

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

博客文章 | 源代码


8
惊人!我喜欢MVC + U!
Piotr Kula 2012年

2
敬畏该解决方案的优雅
BraveNewMath 2012年

3
如果要将CORS限制为自己的域,则可以轻松地扩展属性以接受特定来源。
Petrus Theron,

2
您应该能够将此添加到App_Start \ FilterConfig中的RegisterHttpFilters中吗?这样做会将其应用于项目中的所有Api控制器。将此与上面的pate注释结合起来,可以将CORS限制为所有控制器的域。
bdwakefield

9
我最近将我们的项目更新为MVC 5,并尝试执行此操作。即使在过滤器中添加标头似乎也不起作用。当我在网络中查看请求时,响应中没有标题。为了使它正常工作,还有其他需要做的事情吗?
Kneemin '16

121

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

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

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


1
我不记得为什么了,但是这种方法在IIS 7+中并不总是有效
LaundroMatt 2013年

嗯 我认为无法使用的唯一原因是,如果请求来自非CORS浏览器。但我会继续调查。
sellmeadog 2013年

29
而且,这将使整个网站都对CORS友好。如果有人只想将单个动作或控制器标记为对CORS友好,那么可接受的答案会更好。
Lev Dubinets

1
如果看到ASP.Net部分,则提示“注意:此方法与IIS6,IIS7经典模式和IIS7集成模式兼容。”
percebus 2013年

1
在SharePoint环境中发布应用程序时,我遇到了跨域问题。当我在本地环境上运行我的应用程序时,我的应用程序运行良好,但是当我将其发布到Azure上的我的共享点站点上时,它会重定向到Ajax.Begin表单调用上的错误页面。我尝试了此解决方案,但对我不起作用。还有其他选择吗?
Jyotsna Wadhwani

22

我遇到了一个问题,浏览器拒绝提供请求通过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);
    }
}

这特别有用,谢谢。
cklimowski

15

这真的很简单,只需在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>

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

问候 :)


如果您打算使用授权查询,则在Access-Control-Allow-Header中添加“授权”也很有用。
AFract

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>

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

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

顺便说一句,在站点限制中,您需要在“安全性”部分的“系统高级设置”中添加*
Bishoy Hanna 2014年

我需要在哪些文件中更新控制器头?
user3281466


5

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

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

4

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

  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: "*")]


我必须使用此方法,因为我需要在请求中设置自定义标头,并且自定义属性方法不适用于浏览器的飞行前请求。这似乎在所有情况下都有效。
lehn0058 '02

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

2

我们可以通过多种方法来传递Access-Control-Expose-Headers。

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

    config.EnableCors(new EnableCorsAttribute(“ ”,headers:“ ”,方法:“ *”,exposedHeaders:“ TestHeaderToExpose”){SupportsCredentials = true});

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

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

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

快乐编码!


1

经过一个整夜的努力,我终于开始工作了。经过一些调试后,我发现我遇到的问题是我的客户端正在发送一个所谓的预检选项请求,以检查是否允许应用程序发送带有提供的原始,方法和标头的发布请求。我不想使用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);
            }
        }
    }
}

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

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

0

在Web.config中输入以下内容

<system.webServer>
<httpProtocol>
  <customHeaders>
    <clear />     
    <add name="Access-Control-Allow-Credentials" value="true" />
    <add name="Access-Control-Allow-Origin" value="http://localhost:123456(etc)" />
  </customHeaders>
</httpProtocol>

0

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

这是配置示例:

    <system.webServer>
        <cors enabled="true" failUnlistedOrigins="true">
            <add origin="*" />
            <add origin="https://*.microsoft.com"
                 allowCredentials="true"
                 maxAge="120"> 
                <allowHeaders allowAllRequestedHeaders="true">
                    <add header="header1" />
                    <add header="header2" />
                </allowHeaders>
                <allowMethods>
                     <add method="DELETE" />
                </allowMethods>
                <exposeHeaders>
                    <add header="header1" />
                    <add header="header2" />
                </exposeHeaders>
            </add>
            <add origin="http://*" allowed="false" />
        </cors>
    </system.webServer>

0

我正在使用DotNet Core MVC,并且在与nuget包,Startup.cs,属性以及这个位置打了几个小时之后,我只是将其添加到了MVC操作中:

Response.Headers.Add("Access-Control-Allow-Origin", "*");

我意识到这很笨拙,但这只是我所需要的,没有其他想要添加这些标头的东西了。我希望这可以帮助其他人!

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.