MVC web api: İstenen kaynakta 'Access-Control-Allow-Origin' başlığı yok


128

Bu makalede yazılan her şeyi denedim: http://www.asp.net/web-api/overview/security/enoking-cross-origin-requests-in-web-api , ama hiçbir şey işe yaramıyor. AngularJS kullanarak başka bir etki alanında kullanmak için webAPI2'den (MVC5) veri almaya çalışıyorum.

denetleyicim şuna benziyor:

namespace tapuzWebAPI.Controllers
{
    [EnableCors(origins: "http://local.tapuz.co.il", headers: "*", methods: "*", SupportsCredentials = true)]
    [RoutePrefix("api/homepage")]
    public class HomePageController : ApiController
    {
        [HttpGet]
        [Route("GetMainItems")]
        //[ResponseType(typeof(Product))]
        public List<usp_MobileSelectTopSecondaryItemsByCategoryResult> GetMainItems()
        {


            HomePageDALcs dal = new HomePageDALcs();
            //Three product added to display the data

            //HomePagePromotedItems.Value.Add(new HomePagePromotedItem.Value.FirstOrDefault((p) => p.ID == id));


            List<usp_MobileSelectTopSecondaryItemsByCategoryResult> items = dal.MobileSelectTopSecondaryItemsByCategory(3, 5);
            return items;

        }      
    }
}

1
Ayrıca cors istemek için açısal kodunuzu paylaşın
harishr

2
Muhtemelen açısal koduyla ilgili bir sorun yoktur çünkü CORS sorunlarının çoğu yalnızca sunucu yapılandırmasından kaynaklanmaktadır
sam

Aynı tür bir kuruluma sahibim, API üzerinde var olmayan bir eylem istediğimde ve WebApi bir 404 döndürdüğünde, CORS başlığının eksik olduğunu ve tarayıcının şikayet edeceğini fark ettim. Yani, belki de bu kadar basittir.
Robin van der Knaap

Yanıtlar:


296

Sen etkinleştirmeniz gerekir CORS'yi sizin de Web Api . CORS'u global olarak etkinleştirmenin daha kolay ve tercih edilen yolu, aşağıdakileri web.config dosyasına eklemektir.

<system.webServer>
  <httpProtocol>
    <customHeaders>
      <add name="Access-Control-Allow-Origin" value="*" />
      <add name="Access-Control-Allow-Headers" value="Content-Type" />
      <add name="Access-Control-Allow-Methods" value="GET, POST, PUT, DELETE, OPTIONS" />
    </customHeaders>
  </httpProtocol>
</system.webServer>

Lütfen, Yöntemlerin kullanmak yerine tek tek belirtildiğini unutmayın *. Bunun nedeni, kullanım sırasında meydana gelen bir hata olmasıdır *.

CORS'u kodla da etkinleştirebilirsiniz .

Güncelleme
aşağıdaki Nuget paketi gereklidir: Microsoft.AspNet.WebApi.Cors.

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        config.EnableCors();

        // ...
    }
}

Ardından [EnableCors]özelliği Eylemler veya Denetleyicilerde bunun gibi kullanabilirsiniz

[EnableCors(origins: "http://www.example.com", headers: "*", methods: "*")]

Veya global olarak kaydettirebilirsiniz

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        var cors = new EnableCorsAttribute("http://www.example.com", "*", "*");
        config.EnableCors(cors);

        // ...
    }
}

Ayrıca uçuş öncesi işlemek için gereken Options istekleri ile HTTP OPTIONSistekleri.

Web APIOptionsgerçekten desteklemek için yapılandırıldığını onaylamak için isteğe yanıt vermesi gerekiyor CORS.

Bunu halletmek için yapmanız gereken tek şey boş bir yanıt göndermek . Bunu eylemlerinin içinde yapabilirsin ya da küresel olarak şu şekilde yapabilirsin:

# Global.asax.cs
protected void Application_BeginRequest()
{
    if (Request.Headers.AllKeys.Contains("Origin") && Request.HttpMethod == "OPTIONS")
    {
        Response.Flush();
    }
}

Bu fazladan kontrol, APIsyalnızca kabul etmek üzere tasarlanan GETve POSTisteklerin kötüye kullanılmamasını sağlamak için eklenmiştir . Bu fiil mevcut olmadığında tasarlanmış bir kişiye DELETEistek göndermeyi hayal edin . Sonuç tahmin edilemez ve sonuçlar tehlikeli olabilir .API


4
Cevabınız bana yardımcı oldu. Kod tabanlı çözümlerle elimden gelen her şeyi denedim. Cevabınızı okuyana kadar web.config seçeneğini denemedim. İşe yarayan tek kişi oydu. Herhangi bir fikrin neden? OData ile Web API 2 kullanıyorum. Yine de teşekkürler! :)
Felipe Correa

1
İleride başvurmak üzere, bunun için ihtiyacınız olan NuGet paketi "Microsoft.AspNet.WebApi.Cors" dir.
BrainSlugs83

2
Tüm cevabınızı takip ettim ve iki sorum var: Application_BeginRequest () nerede çağrılmalı? ve ikincisi, aynı yöntemde .Contains ("Origin") bende gerçekten derlenmiyor, bu yöntem nereden, String.Contains veya Linq.Contains'den geliyor?
meJustAndrew

2
unutmayın, farklı bir bağlantı noktası # farklı bir etki alanı oluşturur ve bu bir getcha olabilir. foo.com , foo.com'dan farklı bir etki alanıdır
8080

2
Hayatımı kurtarıyorsun;)
Paweł Groński

26

@ Mihai-Andrei Dinculescu'nun cevabı doğru, ancak arama yapanların yararına, bu hataya neden olabilecek ince bir nokta da var.

URL'nizin sonuna bir "/" eklemek, EnableCors'un tüm durumlarda (örneğin ana sayfadan) çalışmasını durduracaktır.

Yani bu işe yaramayacak

var cors = new EnableCorsAttribute("http://testing.azurewebsites.net/", "*", "*");
config.EnableCors(cors);

ama bu işe yarayacak:

var cors = new EnableCorsAttribute("http://testing.azurewebsites.net", "*", "*");
config.EnableCors(cors);

EnableCors Özniteliği kullanılıyorsa, efekt aynıdır.


Teşekkürler!! Yardımcı oldu.
Ankit Sahrawat

23

Mihai-Andrei Dinculescu'nun belirttiği yukarıdaki tüm adımları takip ettim .
Ancak benim durumumda, 1 adıma daha ihtiyacım vardı çünkü http OPTIONS, Web.Config'de aşağıdaki satırdan devre dışı bırakıldı.

<remove name="OPTIONSVerbHandler" />

Web.Config'den kaldırdım (aşağıdaki gibi yorumlayın) ve Cors bir cazibe gibi çalışıyor

<handlers>
  <!-- remove name="OPTIONSVerbHandler" / -->
</handlers>

9

Bunun nedeni, Cors nuget paketlerinin yüklenmesi olabilir.

Nuget'ten cors yükledikten ve etkinleştirdikten sonra sorunla karşılaşırsanız, web API'sini yeniden yüklemeyi deneyebilirsiniz.

Paket yöneticisinden çalıştırın Update-Package Microsoft.AspNet.WebApi -reinstall


Bu tam olarak benim için buydu. System.Web.Http.Cors'ı yükledim ve sonra kaldırdım, bu da WebApi'yi 5.2.2 ile 5.2.3 arasında yanlış (yeni yükseltilmiş) sürümde
bıraktı

7

CORS'u doğru şekilde yapılandırdığınızdan emin olmak için bunu deneyin:

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

Hala çalışmıyor? HTTP üstbilgilerinin varlığını kontrol edin.


çalışıp çalışmadığını kontrol etmek için, destek bilgilerini de kaldırmak daha iyidir, belirli koşullarda cors'u devre dışı bırakır
harishr

En iyi yanıt, çünkü tüm sitem için CORS'u etkinleştirmek istemiyorum, sadece belirli uç noktalar. config.EnableCors()bunun için de gereklidir.
Csaba Toth

4

Herhangi bir CORS protokolünün çalışması için, her uç noktada bir OPTIONS yöntemine (veya bu yöntemle genel bir filtreye) sahip olmanız ve bu başlıkları döndürmeniz gerekir:

Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET, POST, PUT, DELETE
Access-Control-Allow-Headers: content-type

Bunun nedeni, tarayıcının önce sunucunuzu 'test etmek' ve yetkilendirmeleri görmek için bir OPTIONS isteği göndermesidir.


2

Korslarla ilgili bir sonraki davayı yakalarım. Belki birisi için yararlı olur. Sunucunuza 'WebDav Redirector' özelliğini eklerseniz, PUT ve DELETE istekleri başarısız olur.

Bu nedenle, IIS sunucunuzdan 'WebDAVModule'u kaldırmanız gerekecek:

  • "IIS modüllerinin Yapılandırmasında, web sunucunuzda varsa, WebDAVModülünü döngüleyin, sonra kaldırın".

Veya yapılandırmanıza ekleyin:

<system.webServer>
<modules>
  <remove name="WebDAVModule"/>
</modules>
<handlers>
  <remove name="WebDAV" />
  ...
</handlers>


2

Buna çok geç geldiğimi biliyorum. Ancak, arayan herkes için, SONUNDA benim için işe yarayan şeyi yayınlayacağımı düşündüm. Bunun en iyi çözüm olduğunu iddia etmiyorum - sadece işe yaradığını.

WebApi hizmetimiz config.EnableCors (corsAttribute) yöntemini kullanır. Bununla birlikte, buna rağmen, uçuş öncesi taleplerde yine de başarısız olacaktır. @ Mihai-Andrei Dinculescu'nun cevabı bana ipucu sağladı. Her şeyden önce, seçenek isteklerini temizlemek için Application_BeginRequest () kodunu ekledim. O STILL benim için çalışmadı. Sorun, WebAPI'nin hala OPTIONS isteğine beklenen başlıklardan hiçbirini eklememesidir. Tek başına yıkamak işe yaramadı - ama bana bir fikir verdi. Aksi takdirde web.config aracılığıyla eklenecek özel üstbilgileri OPTIONS isteğinin yanıtına ekledim. İşte kodum:

protected void Application_BeginRequest()
{
  if (Request.Headers.AllKeys.Contains("Origin") && Request.HttpMethod == "OPTIONS")
  {
    Response.Headers.Add("Access-Control-Allow-Origin", "https://localhost:44343");
    Response.Headers.Add("Access-Control-Allow-Headers",
      "Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With");
    Response.Headers.Add("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
    Response.Headers.Add("Access-Control-Allow-Credentials", "true");
    Response.Flush();
  }
}

Açıkçası, bu yalnızca OPTIONS istekleri için geçerlidir. Diğer tüm fiiller CORS konfigürasyonu tarafından işlenir. Buna daha iyi bir yaklaşım varsa, tamamen kulağım. Bu bana bir hile gibi geliyor ve başlıkların otomatik olarak eklenmesini tercih ederim, ancak sonunda işe yarayan ve devam etmeme izin veren şey buydu.


1

@ Mihai-Andrei Dinculescu'nun cevabı benim için çalıştı, örneğin:

  • <httpProtocol>Web.config <system.webServer>bölümüne bir ekleme
  • İçin boş yanıt dönen OPTIONSsözü aracılığıyla istekleri Application_BeginRequest()halindeglobal.asax

Çekinin Request.Headers.AllKeys.Contains("Origin")benim için çalışmaması dışında , çünkü istek origingküçük harfle bir içeriyordu . Tarayıcımın (Chrome) CORS istekleri için bu şekilde gönderdiğini düşünüyorum.

Bunun yerine , çekinin büyük / küçük harfe duyarlı olmayan bir varyantını kullanarak bunu biraz daha genel bir şekilde çözdümContains : if (culture.CompareInfo.IndexOf(string.Join(",", Request.Headers.AllKeys), "Origin", CompareOptions.IgnoreCase) >= 0) {


0

Web.config dosyanızda security \ requestFiltering düğümleriniz varsa aşağıdaki gibi:

<security>
  <requestFiltering>
    <verbs allowUnlisted="false">
      <add verb="GET" allowed="true" />
      <add verb="POST" allowed="true" />
      <add verb="PUT" allowed="true" />
      <add verb="DELETE" allowed="true" />
      <add verb="DEBUG" allowed="true" />          
    </verbs>
  </requestFiltering>

bunu da eklediğinizden emin olun

<add verb="OPTIONS" allowed="true" />

0

Bu cevapta verilen yöntemler dahil internette bulabildiğim her şeyi denedim. Neredeyse bütün gün sorunu çözmeye çalıştıktan sonra, benim için bir cazibe gibi çalışan çözümü buldum.

App_Start klasöründeki WebApiConfig dosyasında , tüm kod satırlarını yorumlayın ve aşağıdaki kodu ekleyin:

`public static void Register(HttpConfiguration config)
    {
        // Web API configuration and services
        config.EnableCors();
        var enableCorsAttribute = new EnableCorsAttribute("*",
                                           "Origin, Content-Type, Accept",
                                           "GET, PUT, POST, DELETE, OPTIONS");
        config.EnableCors(enableCorsAttribute);
        // Web API routes
        config.MapHttpAttributeRoutes();

        config.Routes.MapHttpRoute(
            name: "DefaultApi",
            //routeTemplate: "api/{controller}/{id}",
            routeTemplate: "api/{controller}/{action}/{id}",
            defaults: new { id = RouteParameter.Optional }
        );
        config.Formatters.Add(new BrowserJsonFormatter());
    }

    public class BrowserJsonFormatter : JsonMediaTypeFormatter
    {
        public BrowserJsonFormatter()
        {
            this.SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/html"));
            this.SerializerSettings.Formatting = Formatting.Indented;
        }

        public override void SetDefaultContentHeaders(Type type, HttpContentHeaders headers, MediaTypeHeaderValue mediaType)
        {
            base.SetDefaultContentHeaders(type, headers, mediaType);
            headers.ContentType = new MediaTypeHeaderValue("application/json");
        }
    }`

0

İnsanların bunu ilk başta çok açık bulacağını biliyorum, ama gerçekten bunu bir düşünün. Yanlış bir şey yaptıysanız bu genellikle olabilir.

Örneğin, ana bilgisayar dosyama bir ana bilgisayar girişi eklemediğim için bu sorunu yaşadım. Gerçek sorun DNS çözümlemesiydi. Ya da sadece temel URL'yi yanlış anladım.

Bazen kimlik belirteci bir sunucudan geldiyse bu hatayı alıyorum, ancak onu başka bir sunucuda kullanmaya çalışıyorum.

Bazen kaynağı yanlış yaptıysanız bu hatayı alırsınız.

CORS ara yazılımını zincire çok geç koyarsanız bunu elde edebilirsiniz.


0

WebApiCOnfig.cs gibi, sağlayıcıdaki GrantResourceOwnerCredentials yöntemi ve Denetleyici Üstbilgisi özniteliği gibi CORS'u etkinleştiren birden fazla yerden kaçının.

  1. Kullandığınız DB ile etkileşimde sorun olan Web.
  2. AWS Cloud Web API ve DB'nin VPC'si farklıysa.

Aşağıdaki kod, erişim kontrolüne izin vermeyi düzeltmek için yeterlidir. // app.Cors uygulamasının konfigürasyonun kod satırının en üstünde olması gerektiğinden emin olun.

   public partial class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
            //All other configurations
        }
    }

Bu benim sorunumu yavaşlattı.


0

Bu sorun, farklı bir etki alanından veya farklı bir bağlantı noktasından erişmeye çalıştığınızda ortaya çıkar.

Visual Studio kullanıyorsanız, Araçlar> NuGet Paket Yöneticisi> Paket Yöneticisi Konsolu'na gidin. Orada NuGet Paketi Microsoft.AspNet.WebApi.Cors'ı yüklemeniz gerekir

Install-Package Microsoft.AspNet.WebApi.Cors

Ardından PROJECT> App_Start> WebApiConfig'de CORS'u etkinleştirin

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        
        //Enable CORS. Note that the domain doesn't have / in the end.
        config.EnableCors(new EnableCorsAttribute("https://tiagoperes.eu",headers:"*",methods:"*"));

        ....

    }
}

Başarıyla kurulduktan sonra çözümü oluşturun ve bu yeterli olmalıdır

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.