JavaScript kodum geldiğinde Postacı neden “İstenen kaynakta 'Erişim-Denetim-İzin Verme Başlığı' başlığı yok” hatası almıyor?


2502

Mod notu : Bu soru, Postacı'nın neden XMLHttpRequest ile aynı şekilde CORS kısıtlamalarına tabi olmadığına ilişkindir. Bu soru, "Hayır 'Access-Control-Allow-Origin' ..." hatasının nasıl düzeltileceği ile ilgili değildir .

Lütfen göndermeyi durdurun :

  • Güneş altındaki her dil / çerçeve için CORS yapılandırmaları. Bunun yerine , ilgili dilinizin / çerçevenizin sorusunu bulun .
  • CORS'i atlatma talebine izin veren 3. taraf hizmetleri
  • Çeşitli tarayıcılar için CORS'yi kapatmak için komut satırı seçenekleri

RESTful API yerleşik Flask bağlanarak JavaScript kullanarak yetkilendirme yapmaya çalışıyorum . Ancak, isteği yaptığımda aşağıdaki hatayı alıyorum:

XMLHttpRequest http: // myApiUrl / login yükleyemiyor . İstenen kaynakta 'Access-Control-Allow-Origin' başlığı yok. Bu nedenle 'null' kaynağına erişime izin verilmiyor.

API veya uzak kaynağın başlığı ayarlaması gerektiğini biliyorum, ancak Chrome uzantısı Postacı aracılığıyla istekte bulunduğumda neden işe yaradı ?

Bu istek kodudur:

$.ajax({
    type: "POST",
    dataType: 'text',
    url: api,
    username: 'user',
    password: 'pass',
    crossDomain : true,
    xhrFields: {
        withCredentials: true
    }
})
    .done(function( data ) {
        console.log("done");
    })
    .fail( function(xhr, textStatus, errorThrown) {
        alert(xhr.responseText);
        alert(textStatus);
    });

32
Localhost'tan istek mi yapıyorsunuz veya HTML'yi doğrudan yürütüyor musunuz?
MD. Sahib Bin Mahboob

@ MD.SahibBinMahboob Sorunuzu anlarsam localhost'tan istekte bulunurum - bilgisayarımda sayfa var ve sadece çalıştırıyorum. Siteyi hosting üzerine dağıttığımda aynı sonuç verdi.
Bay Jedi


8
Daha fazla okumak isteyen herkes için MDN'nin ajax ve çapraz menşe istekleri hakkında iyi bir makalesi vardır: developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS
Sam Eaton

1
Düğüm js bu hata türü için önemli bir not. Erişim başlıklarınızı, rotalarınızı ayarlamaya başlamadan ÖNCE server.js dosyanızın başlangıcında ayarlamalısınız. Aksi takdirde, her şey harika çalışır, ancak uygulamanızdan istekte bulunduğunuzda bu hatayı alırsınız.
Alex J

Yanıtlar:


1346

Eğer doğru anladıysam , sayfanızın açık olduğundan farklı bir alan adına XMLHttpRequest yapıyorsunuz . Bu nedenle tarayıcı, genellikle güvenlik nedenleriyle aynı kaynaktan bir istekte bulunmasına izin verdiği için engelliyor. Bir etki alanları arası istek yapmak istediğinizde farklı bir şey yapmanız gerekir. Bunu başarmak için bir öğretici CORS kullanmaktır .

Postacı kullandığınızda bu politika tarafından kısıtlanmazlar. Cross-Origin XMLHttpRequest tarafından alıntılanmıştır :

Normal web sayfaları, uzak sunuculardan veri göndermek ve almak için XMLHttpRequest nesnesini kullanabilir, ancak bunlar aynı başlangıç ​​politikasıyla sınırlıdır. Uzantılar çok sınırlı değil. Bir uzantı, ilk önce çapraz kaynak izinleri istediği sürece uzak sunucularla kendi kaynağı dışında konuşabilir.


7
Haklısın. Sayfamdan farklı bir alan adına istekte bulunuyorum. API sunucuda ve localhost'tan istek çalıştırıyorum. Cevabı kabul etmeden önce bana "isteği doğrudan yerine getirmek" ne anlama geldiğini açıklayabilir misiniz? POSTMAN alan adı kullanmıyor mu?
Bay Jedi

181
Tarayıcı isteği engellemiyor. Kökenler arası ajax isteklerini açıkça engelleyen tek tarayıcılar IE7 veya daha eski sürümlerdir. IE7 ve daha eski tarayıcılar dışındaki tüm tarayıcılar, CORS spesifikasyonunu (IE8 ve IE9 kısmen) uygular. Tek yapmanız gereken, isteğe bağlı olarak uygun başlıkları döndürerek API sunucunuzdaki CORS isteklerine kaydolmaktır. Mzl.la/VOFrSz adresindeki CORS kavramlarını okumalısınız . Postacı taleplerini XHR aracılığıyla da gönderir. Postacı kullanırken aynı sorunu görmüyorsanız, bu aynı talebi postacı aracılığıyla bilmeden göndermediğiniz anlamına gelir.
Ray Nicholus

10
@ MD.SahibBinMahboob Postacı "java / python'unuzdan" bir istek göndermiyor. İsteği doğrudan tarayıcıdan gönderiyor. Chrome uzantılarındaki XHR, özellikle çapraz kaynak talepleri söz konusu olduğunda biraz farklı çalışır .
Ray Nicholus

250

UYARI: Kullanmak Access-Control-Allow-Origin: *API / web sitenizi siteler arası istek sahteciliği (CSRF) saldırılarına karşı savunmasız bırakabilir . Bu kodu kullanmadan önce riskleri anladığınızdan emin olun .

PHP kullanıyorsanız bunu çözmek çok kolaydır . PHP sayfanızın başına isteği işleyen şu komut dosyasını eklemeniz yeterlidir:

<?php header('Access-Control-Allow-Origin: *'); ?>

Eğer kullanıyorsanız Düğüm-kırmızı İzin vermek zorunda CORS içinde node-red/settings.jsaşağıdaki satırları un-yorum yaparak dosyaya:

// The following property can be used to configure cross-origin resource sharing
// in the HTTP nodes.
// See https://github.com/troygoode/node-cors#configuration-options for
// details on its contents. The following is a basic permissive set of options:
httpNodeCors: {
 origin: "*",
 methods: "GET,PUT,POST,DELETE"
},

Flask'ı soru ile aynı kullanıyorsanız ; ilk yüklemen varflask-cors

$ pip install -U flask-cors

Ardından uygulamanıza Flask cors ekleyin.

from flask_cors import CORS

Basit bir uygulama şöyle görünecektir:

from flask import Flask
from flask_cors import CORS

app = Flask(__name__)
CORS(app)

@app.route("/")
def helloWorld():
  return "Hello, cross-origin-world!"

Daha fazla ayrıntı için Flask belgelerine bakabilirsiniz .


93
ve güvenli değil
llazzaro

153
Sen olmamalıdır kapatmak ne onun bilmiyorum çünkü CORS'yi. Bu korkunç bir cevap.
meagar

124
Güvenli olmasa da, soru güvenlikle ilgili değil, görevin nasıl gerçekleştirileceği ile ilgiliydi. Bu, bir geliştiricinin alanlar arası AJAX istekleriyle uğraşırken seçmesi gereken seçeneklerden biridir. Sorunu çözmeme yardımcı oldu ve uygulamam için verilerin nereden geldiğini umursamıyorum. Ben hedef etki alanı PHP ile tüm girdiyi dezenfekte, bu yüzden, birisi ona önemsiz göndermek istiyorsanız, deneyelim. Buradaki ana nokta, etki alanları arası AJAX'a hedef etki alanından izin verilebilir. Cevap için +1.
ZurabWeb

23
Piero'nun verdiği genel mesajı kabul ederken, bunun özellikle güvenlikle ilgili olmadığını, ancak güvenlik endişe verici olduğunu söylüyor. Bunun en azından "Bu genellikle kötü! Ne yaptığınızı bilmiyorsanız bunu yapmayın! İşte bununla ilgili daha fazla belge: ..." gibi bir şey söylemiş olmalı ve belki de nedenini kısaca açıklamalıyım. Birinin buraya gelmesinden nefret ederdim ve sadece "Oh, bu başlığı ekleyebilir / ayarlayabilirim ve iyiyim!" ve tam sonuçları bilmiyorum. Demek istediğim, onları araştırmak ve hepsi, ama yine de.
Thomas F.15

4
Bu yanıtı beğendim ... Aynı sorunum var ve çözüyor ... Bazı güvenlik sorunları olduğunu açıkladı, ama bu başka bir sorun ve herkesin bu sorunu bireysel olarak düşünmesine ve çözmesine izin verin ...
Ari Waisberg

64

Çünkü
$ .ajax ({type: "POST" - OPTIONS
$ .post'u çağırır ( - POST'u çağırır)

Her ikisi de farklı. Postacı "POST" ifadesini düzgün bir şekilde çağırır, ancak çağırdığımızda "SEÇENEKLER" olur.

C # web hizmetleri için - Web API'sı

Lütfen web.config dosyanıza <system.webServer> etiketi altında aşağıdaki kodu ekleyin . Bu çalışacak:

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

Lütfen Ajax çağrısında herhangi bir hata yapmadığınızdan emin olun

jQuery

$.ajax({
    url: 'http://mysite.microsoft.sample.xyz.com/api/mycall',
    headers: {
        'Content-Type': 'application/x-www-form-urlencoded'
    },
    type: "POST", /* or type:"GET" or type:"PUT" */
    dataType: "json",
    data: {
    },
    success: function (result) {
        console.log(result);
    },
    error: function () {
        console.log("error");
    }
});

Not: Eğer içerik indirmek arıyorsanız bir üçüncü taraf web sitesinden daha sonra bu size yardımcı olmayacaktır . Aşağıdaki kodu deneyebilirsiniz, ancak JavaScript'i deneyemezsiniz.

System.Net.WebClient wc = new System.Net.WebClient();
string str = wc.DownloadString("http://mysite.microsoft.sample.xyz.com/api/mycall");

Bu yapılandırma, Azure Hizmetlerindeki Wordpress'te aynı hatayı çözdü. Teşekkürler.
Andre Mesquita

9
Harici alanlardan gelen istekleri önlemek için belirli bir başlangıç ​​değeri kullanmanızı öneririm. Örneğin, *kullanım yerinehttps://www.myotherdomain.com
pechar


8

CORS kısıtlaması uygulamak, sunucu tarafından tanımlanan ve tarayıcı tarafından uygulanan bir güvenlik özelliğidir .

Tarayıcı, sunucunun CORS politikasına bakar ve saygı duyar.

Ancak, Postacı aracı sunucunun CORS ilkesi hakkında rahatsız etmez.

Bu nedenle CORS hatası tarayıcıda görünür, ancak Postacı'da görünmez.


1
Evet, bu küçük detayın neden biraz ilgiyi hak ettiğini yeterince vurgulayamıyorum. Güvenlik söz konusu olduğunda, CORS'nin onu uygulayan müşteri kadar güçlü olduğunu belirtmek en önemlisidir . Basit bir HttpClient (sunucu tarafı kodu) aldığınız ve isteklerinizi yapan bir proxy oluşturduğunuzu düşünün ... Güvenlik tamamen atlatılabilir, gerçekten CORS standardını kötü bir çözüm olarak bırakır
Christopher Bonitz

7

Aşağıdaki araştırmada API olarak, sorunuzdaki http: // myApiUrl / login yerine http://example.com kullanıyorum , çünkü bu ilk çalışma çalışıyor.

Sayfanızın http: //my-site.local: 8088 adresinde olduğunu varsayıyorum .

Farklı sonuçlar görmenizin nedeni Postacı:

  • üstbilgiyi ayarla Host=example.com(API'nız)
  • Başlık ayarlanmadı Origin

Bu, site ve API aynı etki alanına sahip olduğunda tarayıcıların istek gönderme yöntemine benzer (tarayıcılar da başlık öğesini ayarlar Referer=http://my-site.local:8088, ancak Postacı'da görmüyorum). Ne zaman Originbaşlık edilir değil set, genellikle sunucuları varsayılan olarak bu tür istekleri verir.

Resim açıklamasını buraya girin

Postacı'nın istekleri göndermenin standart yolu budur. Ancak , siteniz ve API'nız farklı alan adlarına sahip olduğunda bir tarayıcı istekleri farklı şekilde gönderir ve ardından CORS oluşur ve tarayıcı otomatik olarak:

  • üstbilgiyi ayarlar Host=example.com(sizinki API olarak)
  • üstbilgiyi ayarlar Origin=http://my-site.local:8088(siteniz)

(Başlık Referer, ile aynı değere sahiptir Origin). Ve şimdi Chrome'un Konsol ve Ağlar sekmesinde şunları göreceksiniz:

Resim açıklamasını buraya girin

Resim açıklamasını buraya girin

Eğer varsa Host != Originbu genellikle, bu CORS olduğu ve sunucu böyle bir talebi algıladığında varsayılan olarak engelleme yapar .

Origin=nullHTML içeriğini yerel bir dizinden açtığınızda ayarlanır ve bir istek gönderir. Aynı durum, <iframe>aşağıdaki snippet'teki gibi bir istek gönderdiğinizde (ancak burada Hostbaşlık hiç ayarlanmamıştır) - genel olarak, HTML spesifikasyonunun opak kökenli olduğu her yerde bunu çevirebilirsiniz Origin=null. Bununla ilgili daha fazla bilgiyi burada bulabilirsiniz .

fetch('http://example.com/api', {method: 'POST'});
Look on chrome-console > network tab

Basit bir CORS isteği kullanmazsanız, tarayıcı genellikle ana isteği göndermeden önce otomatik olarak bir SEÇENEK isteği gönderir - daha fazla bilgi burada . Aşağıdaki snippet bunu gösterir:

fetch('http://example.com/api', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json'}
});
Look in chrome-console -> network tab to 'api' request.
This is the OPTIONS request (the server does not allow sending a POST request)

Sunucunuzun yapılandırmasını CORS isteklerine izin verecek şekilde değiştirebilirsiniz.

İşte nginx (nginx.conf dosyası) üzerinde CORS'yi açan bir örnek yapılandırma - always/"$http_origin"nginx ve "*"Apache için ayarlara çok dikkat edin - bu, CORS'nin herhangi bir alandan engellemesini kaldırır.

Apache'de (.htaccess dosyası) CORS'yi açan örnek bir yapılandırma


2

Farklı kullanım durumlarında aynı hatayla karşılaşıldı.

Kullanım Durumu: Köşede Spring REST bitiş noktasını çağırmaya çalışıldığında kromda.

resim açıklamasını buraya girin

Çözüm: İlgili Controller Sınıfının üstüne @CrossOrigin ("*") ek açıklaması ekleyin .

resim açıklamasını buraya girin


Güvenlik için * yerine localhost kullanıyorum
neo7bf

-1

Orta katmanınız olarak .NET kullanıyorsanız, route özelliğini açıkça kontrol edin, örneğin,

Böyle bir şey yaşadım,

[Route("something/{somethingLong: long}")] //Space.

Bununla düzeltildi,

[Route("something/{somethingLong:long}")] //No space

-1

Yalnızca .NET Core Web API projesi için aşağıdaki değişiklikleri ekleyin:

  1. Startup.cs dosyasının yöntemindeki services.AddMvc()satırdan sonra aşağıdaki kodu ekleyin ConfigureServices():
services.AddCors(allowsites=>{allowsites.AddPolicy("AllowOrigin", options => options.AllowAnyOrigin());
            });
  1. Startup.cs dosyasının yöntemine app.UseMvc()satırdan sonra aşağıdaki kodu ekleyin Configure():
app.UseCors(options => options.AllowAnyOrigin());
  1. Etki alanı dışında erişmek istediğiniz denetleyiciyi açın ve bu özelliği denetleyici düzeyinde ekleyin:
[EnableCors("AllowOrigin")]
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.