ASP.Net MVC'de Access-Control-Allow-Origin'i ayarlama - mümkün olan en basit yöntem


206

Basit bir eylem yöntemim var, bu biraz json döndürüyor. Ajax.example.com üzerinde çalışır. Buna someothersite.com adresinden başka bir siteden erişmem gerekiyor.

Aramaya çalışırsam, beklenen ...:

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

Bunu aşmanın iki yolunu biliyorum: JSONP ve başlık ayarlamak için özel bir HttpHandler oluşturma .

Daha basit bir yolu yok mu?

Basit bir eylem için izin verilen kökenlerin bir listesini tanımlamak ya da basit bir şekilde herkese izin vermek mümkün değil mi? Belki bir eylem filtresi?

Optimal olurdu ...:

return json(mydata, JsonBehaviour.IDontCareWhoAccessesMe);

1
VNext ve MVC6 için buraya bir göz atın: neelbhatt40.wordpress.com/2015/09/10/…
Neel

Yanıtlar:


381

Düz ASP.NET MVC Denetleyicileri için

Yeni bir özellik oluşturun

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

İşleminizi etiketleyin:

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

ASP.NET Web API için

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

Bir API denetleyicisinin tamamını etiketleyin:

[AllowCrossSiteJson]
public class ValuesController : ApiController
{

Veya bireysel API çağrıları:

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

Internet Explorer için <= v9

IE <= 9, CORS'i desteklemez. Bu istekleri bir proxy üzerinden otomatik olarak yönlendirecek bir javascript yazdım. Her şey% 100 şeffaftır (sadece proxy'imi ve komut dosyasını eklemeniz gerekir).

Nuget kullanarak indirin corsproxyve verilen talimatları izleyin.

Blog gönderisi | Kaynak kodu


8
İnanılmaz! MVC + U luv!
Piotr Kula

2
Bu çözümün zarafetine hayran
BraveNewMath

3
CORS'yi kendi alanlarınızla sınırlandırmak istiyorsanız özelliği belirli bir kaynağı kabul edecek şekilde kolayca genişletebilirsiniz.
Petrus Theron

2
Bunu App_Start \ FilterConfig dosyanızdaki RegisterHttpFilters öğesine ekleyebilmeniz gerekir mi? Bunu yapmak projenizdeki tüm Api denetleyicilerine uygular. Bunu pate'nin yukarıdaki yorumuyla eşleştirmek, tüm kontrolörler için CORS'yi alanlarınızla sınırlandırabilirsiniz.
bdwakefield

9
Yakın zamanda projemizi MVC 5'e güncelledim ve bunu yapmaya çalıştım. Bir filtreye üstbilgi eklemek bile işe yaramıyor. Ağdaki isteği görüntülediğimde, başlık yanıtta yok. Bunun işe yaraması için yapılması gereken başka bir şey var mı?
Kneemin

121

IIS 7+ kullanıyorsanız, system.webServer bölümünde klasörün köküne bir web.config dosyası yerleştirebilirsiniz:

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

Bkz. Http://msdn.microsoft.com/en-us/library/ms178685.aspx Ve: http://enable-cors.org/#how-iis7


1
Nedenini artık hatırlayamıyorum, ancak bu yöntem her zaman IIS 7 ve
sonraki sürümlerinde

Hmm. İşe yaramayacağını düşünebilmemin tek nedeni, bir isteğin CORS olmayan bir tarayıcıdan kaynaklanmasıdır. Ama araştırmaya devam edeceğim.
sellmeadog

29
Ayrıca, bu tüm web sitesinin CORS dostu olmasını sağlayacaktır. Birisi sadece tek bir eylemi veya kontrolörü CORS dostu olarak işaretlemek istiyorsa, kabul edilen cevap çok daha iyidir.
Lev Dubinets

1
ASP.Net bölümünü görürseniz bir ipucu vardır : "Not: bu yaklaşım IIS6, IIS7 Klasik Modu ve IIS7 Tümleşik Modu ile uyumludur."
percebus

1
Uygulamamı SharePoint ortamında yayınladığımda etki alanları arası bir sorunla karşılaşıyorum. Uygulamamı yerel ortamda çalıştırdığımda, uygulamam düzgün çalışıyor, ancak Sharepoint sitemde masmavi olarak yayınladığımda Ajax.Begin form çağrısındaki hata sayfasına yönlendiriyor. Bu çözümü denedim ama benim için işe yaramıyor. Buna başka bir alternatif var mı?
Jyotsna Wadhwani

22

Tarayıcı, istek çerezlerde geçtiğinde (örneğin, xhr vardı withCredentials=true) ve site Access-Control-Allow-Originayarlanmış olduğunda aldığı içeriği sunmayı reddettiği bir sorunla karşılaştım *. (Chrome'daki hata, "Kimlik bilgileri bayrağı doğru olduğunda Access-Control-Allow-Origin'de joker karakter kullanılamaz." İdi.)

@Jgauffin'den gelen cevaba dayanarak, temelde o tarayıcı güvenlik kontrolünün etrafında çalışmanın bir yolu olan bunu yarattım, bu yüzden uyarı emptoru.

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

Bu özellikle faydalıydı, teşekkürler.
cklimowski

15

Bu gerçekten basit, bunu web.config dosyasına ekleyin

<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'de web sunucunuza erişimi olan tüm etki alanlarını, üstbilgilere herhangi bir ajax http isteğinin kullanabileceği tüm olası üstbilgileri koyun, yöntemlerde sunucunuza izin verdiğiniz tüm yöntemleri koyun

Saygılarımızla :)


Yetkili sorguları kullanmayı düşünüyorsanız, Access-Control-Allow-Headers uygulamasına "Yetkilendirme" eklemek de yararlı olabilir.
17'de

9

Bazen OPTIONS fiili de sorunlara neden olur

Basitçe: web.config dosyanızı aşağıdakilerle güncelleyin

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

Web hizmeti / denetleyici başlıklarını httpGet ve httpOptions ile güncelleyin

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

BTW, site sonlandırmasında güvenlik bölümündeki Sistem gelişmiş ayarlarına * eklemeniz gerekir
Bishoy Hanna

denetleyici başlıklarını güncellemem gereken dosyalar nelerdir?
user3281466


5

Bir API kullanıyorsanız, bu satırı yönteminize ekleyin.

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

4

Bu eğitim çok faydalı. Hızlı bir özet vermek için:

  1. Nuget'te bulunan CORS paketini kullanın: Install-Package Microsoft.AspNet.WebApi.Cors

  2. Senin içinde WebApiConfig.csdosyaya eklemek config.EnableCors()için Register()yöntemiyle.

  3. Çekirdekleri işlemeniz gereken denetleyicilere bir özellik ekleyin:

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


Bu yöntemi kullanmak zorunda kaldım çünkü isteğimde özel bir üstbilgi ayarlamam gerekiyordu ve özel öznitelik yöntemi tarayıcıların uçuş öncesi isteği ile çalışmadı. Bu her durumda işe yarıyor gibi görünüyor.
lehn0058

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-Üstbilgilerini iletmenin farklı yolları vardır.

  • Jgauffin'in açıkladığı gibi yeni bir özellik oluşturabiliriz.
  • LaundroMatt'ın açıkladığı gibi web.config dosyasına ekleyebiliriz.
  • Başka bir yol, webApiconfig.cs dosyasına aşağıdaki gibi kod ekleyebilmemizdir.

    config.EnableCors (new EnableCorsAttribute (" ", üstbilgiler: " ", yöntemler: "*", exposedHeaders: "TestHeaderToExpose") {SupportsCredentials = true});

Veya Global.Asax dosyasına aşağıdaki kodu ekleyebiliriz.

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

Seçenekler için yazdım. Lütfen ihtiyacınıza göre değiştirin.

Mutlu Kodlama !!


1

Bütün bir akşam için mücadele ettikten sonra nihayet işe yaradı. Bazı hata ayıklama sonra içine yürüdü sorun bulundu müvekkilim, sağlanan kökeni, yöntemleri ve başlıkları ile bir gönderme isteği göndermek için izin verilip verilmediğini kontrol etmek için sözde ön kontrol seçenekleri isteği göndermek oldu. Owin veya bir APIController kullanmak istemedim, bu yüzden kazmaya başladım ve sadece bir ActionFilterAttribute ile aşağıdaki çözümü buldum. Özellikle "Erişim-Kontrol-İzin Ver-Başlıkları" bölümü çok önemlidir, çünkü burada belirtilen başlıkların isteğinizin göndereceği başlıklarla eşleşmesi gerekir.

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

Son olarak, MVC eylem yöntemim böyle görünüyor. Burada önemli olan HttpVerbs Seçeneklerinden de bahsetmektir, aksi takdirde ön kontrol isteği başarısız olur.

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

0

Web.config alanına aşağıdakileri girin

<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 kullanıyorsanız, IIS CORS modülünü denemenizi öneririm .
Yapılandırması kolaydır ve her tür kontrolör için çalışır.

İşte bir yapılandırma örneği:

    <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 kullanıyorum ve nuget paketleri, Startup.cs, öznitelikleri ve burası ile birkaç saat savaştıktan sonra, sadece MVC eylemine ekledi:

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

Bunun oldukça tıknaz olduğunu fark ettim, ama tüm ihtiyacım olan şeydi ve başka hiçbir şey bu başlıkları eklemek istemedi. Umarım bunun bir başkasına yardımı olur!

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.