Access-Control-Allow-Origin Çoklu Kökenli Etki Alanları?


1049

Access-Control-Allow-OriginÜstbilgiyi kullanarak birden çok çapraz alana izin vermenin bir yolu var mı ?

Farkındayım *, ama çok açık. Gerçekten sadece birkaç alana izin vermek istiyorum.

Örnek olarak, şöyle bir şey:

Access-Control-Allow-Origin: http://domain1.example, http://domain2.example

Yukarıdaki kodu denedim ama Firefox'ta çalışmıyor gibi görünüyor.

Birden fazla alan adı belirtmek mümkün mü yoksa yalnızca bir alan adı ile mi takıldım?



3
En son Firefox kullanılarak ne virgülle ayrılmış, ne de boşlukla ayrılmış alanlar işe yaramadı. Bir etki alanları listesiyle eşleştirmek ve başlıklara tek bir ana bilgisayar koymak hala daha iyi bir güvenliktir ve düzgün çalışır.
Daniel

1
HTTPS için bununla uğraşıyorsanız, bir çözüm buldum .
Alex W

7
Önemli not : sadece cretain etki sağlayanAccess-Control-Allow-Originbaşlığında gelmez değil diğer alanlar bu son nokta (örn REST API yöntemi) üzerinde bir yöntemi tetiklemek anlamına gelir. Bu, izin verilmeyen kökenlerin javascript'te sonucu kullanamayacağı anlamına gelir (tarayıcı bunu sağlar). Belirli etki alanları için bir uç noktaya erişimi kısıtlamak için, izin verilmeyen alanlar için HTTP 401 döndüren bir sunucu tarafı istek filtresi kullanın.
18:41

1
Vary: OriginBirden fazla URL kullanmak istediğinizde her zaman üstbilgi eklemelisiniz
Null

Yanıtlar:


861

Bunu yapmanın önerilen yolu gibi görünüyor, sunucunuzun Origin üstbilgisini istemciden okumasını sağlamak, bunu izin vermek istediğiniz etki alanları listesiyle karşılaştırmak ve eşleşirse Originüstbilginin değerini istemciye tekrar yankılamaktır. Access-Control-Allow-Originkarşılık olarak başlık.

İle .htaccessbunu şöyle yapabilirsiniz:

# ----------------------------------------------------------------------
# Allow loading of external fonts
# ----------------------------------------------------------------------
<FilesMatch "\.(ttf|otf|eot|woff|woff2)$">
    <IfModule mod_headers.c>
        SetEnvIf Origin "http(s)?://(www\.)?(google.com|staging.google.com|development.google.com|otherdomain.example|dev02.otherdomain.example)$" AccessControlAllowOrigin=$0
        Header add Access-Control-Allow-Origin %{AccessControlAllowOrigin}e env=AccessControlAllowOrigin
        Header merge Vary Origin
    </IfModule>
</FilesMatch>

41
Bu, W3C'nin önerileriyle eşleşiyor
Simon B.

153
Bu cevapla ilgili sorunum bana gerçekten yardımcı olmuyor, çünkü bir CDN kullanıyoruz ve açıkçası CDN'nin başlıkları programlı olarak nasıl ayarladığını kontrol edemiyoruz.
BT

6
Aşağıdaki
cevabımda

71
Önbellekler veya CDN'ler bir endişe kaynağıysa, önbellek / CDN'ye farklı Origin istek başlığı değerleri için ayrı yanıtlar vermesini bildirmek için Vary üstbilgisini kullanın. Yanıtınıza "Vary: Origin" gibi bir başlık eklersiniz. : Önbellek / CDN o zaman başlık "Menşe ile bir isteğe bir yanıt göndermesi gerektiğini bilir foo.example.com başlığı": Menşe ile bir talebe ve farklı bir tepki " bar.example.com ".
Sean

10
@saturdayplace, Origin başlığına erişiminiz varsa, CORS'u geçtiniz.
Paul Draper

222

PHP kullanıyorum başka bir çözüm:

$http_origin = $_SERVER['HTTP_ORIGIN'];

if ($http_origin == "http://www.domain1.com" || $http_origin == "http://www.domain2.com" || $http_origin == "http://www.domain3.com")
{  
    header("Access-Control-Allow-Origin: $http_origin");
}

12
Neden stackoverflow.com/a/1850482/11635 adresinde önerilen yaklaşımı kullanmıyorsunuz [ve yalnızca istenen kaynaktan bir joker karakter göndermeyin]? Daha fazla bir şey elde etmeden bu daha fazla müsaade eder mi?
Ruben Bartelink

15
sahip header('Access-Control-Allow-Origin: *')bazen kimlik bayrak doğruysa vahşi kart kullanamazsınız diyor - ne olur header('Access-Control-Allow-Credentials: true')muhtemelen. Bu nedenle, $http_originkoşullar karşılanırsa
Kendine

6
header("Access-Control-Allow-Origin: " . $http_origin);çalışmasını sağlamak için son satırı değiştirin
François Romain

2
HTTP_ORIGIN üstbilgisi tanınmazsa, hiçbir Access-Control-Allow-Origin ayarlanmaz ve kodun tamamen açık bırakılması nedeniyle bu kod hatalı görünür.
Stephen R

9
@StephenR aslında "geniş kapalı" daha doğru olurdu, bunun amacı komut dosyasını diğer alanlara
açmaktır

113

Bu benim için çalıştı:

SetEnvIf Origin "^http(s)?://(.+\.)?(domain\.example|domain2\.example)$" origin_is=$0 
Header always set Access-Control-Allow-Origin %{origin_is}e env=origin_is

Koyulduğunda .htaccess, kesinlikle işe yarayacaktır.


24
benim için en iyi çözüm, ancak bağlantı noktası desteği ekledim (örn . geliştirme için localhost: 3000 ): SetEnvIf Origin "^ http (s)?: // (. + \.)? (localhost | stackoverflow.com | example1.com) ( : [0-9] +)? $ "Origin_is = 0 $
vszurma

2
Stackoverflow çevresindeki birçok cevaptan, bu işe yarayan cevaptı.
Meetai.com

Header set Access-Control-Allow-Credentials true@George'un cevabı gibi çalışmak için eklemem gerekiyordu
99 Sorunlar - Sözdizimi bir tane değil 1

Origin kullandığımda bu kesinlikle işe yarıyor. Ancak bazı durumlarda, Origin bazı isteklerde bulunmaz ve tarayıcıya da özgüdür. Sonra Refererbunun yerine kullanmaya karar verdim Origin. RefererÇalışmaları kullanarak ama sorun, Access-Control-Allow-Originalan adını kesmek Refererve atamak istiyorum tam URL geri ayarlar Access-Control-Allow-Origin. Bunun sonucu gibi bir şey - echo http://example.com/index.php/ab/cd | cut -d'/' -f1,2,3bash komutunda. Aynı şeyi (apache) conf dosyasında yapmak mümkün mü? Herhangi bir fikir?
3AK

1
Bu benim için işe yaramıyor. 2 satır eklediğimde her zaman kod 500 hatası alıyorum. Aslında PHP 5.6.15 kullanıyor
BoCyrill

91

Woff-fontları ile aynı sorunu yaşadım, birden fazla alt alanın erişimi vardı. Alt alan adlarına izin vermek için httpd.conf dosyasına böyle bir şey ekledim:

SetEnvIf Origin "^(.*\.example\.com)$" ORIGIN_SUB_DOMAIN=$1
<FilesMatch "\.woff$">
    Header set Access-Control-Allow-Origin "%{ORIGIN_SUB_DOMAIN}e" env=ORIGIN_SUB_DOMAIN
</FilesMatch>

Birden çok alan için, normal ifadeyi SetEnvIf .


4
Hile yaptı. Normal ifadeyi doğru şekilde ayarladığınızdan emin olun. Ben mesela domain kendisi izin vermek için bir soru işareti eklemek için gerekli (.*\.?example\.org)için example.comve sub.example.com.
trkoch

3
Bunu IIS 7 için nasıl uyarlayacağınız hakkında bir fikriniz var mı?
Mark

Bu amacı yenmek değil mi? Kötü niyetli bir kullanıcının Origin başlık değerini takmasını ne engeller?
Grégory Joseph

1
@ GrégoryJoseph Access-Control-Allow-Origin, talep edebilecek birinden kaynakları gizlemekle ilgili değildir. Kötü amaçlı bir sitenin son kullanıcıların sitenizi aramasını önlemekle ilgilidir. Yazı tipi dosyaları söz konusu olduğunda, bu sadece yazı tiplerinin sıcak bağlantılarını etkili bir şekilde sınırlayabilir, neden (mozilla / firefox) diğer kaynaklar (js, css, vb.)
Tracker1

@trkoch, normal ifadenizde bir hata var, buna da izin verecek subexample.com. Bunu şu şekilde değiştirmelisiniz:((.*\.)?example\.org)
bluesmoon

65

Orijin başlığını alan adınız Nginx ile eşleşiyorsa nasıl tekrar yankılayacağınız aşağıda açıklanmıştır: birden çok alt alan adına sahip bir font sunmak istiyorsanız bu yararlıdır:

location /fonts {
    # this will echo back the origin header
    if ($http_origin ~ "example.org$") {
        add_header "Access-Control-Allow-Origin" $http_origin;
    }
}

Bunun nasıl farklı olduğunu anlayamıyorum: add_header Access-Control-Allow-Origin *; Açıklamak ister misiniz?
Anoyz

bu, tarayıcıya yalnızca belirtilen alan adından istek göndermesi için yetki veren bir başlık döndürür. tahmin eğer tarayıcı başka bir sunucuya erişmek için o sayfada yüklü başka bir etki alanından içerik yetkilendirebilir söyleyebilirim.
mjallday

7
@Anoyz bir şey için "İzin *" izin verilen gelişmiş güvenlik olabilir, ancak izin başlığı için belirtilen ve eşleşen bir ana bilgisayar adı çalışır. Buraya bir örnek, web alanları arası yetkilendirme bilgileri göndermek istiyorsanız, "İzin Ver *" seçeneğini kullanamazsınız
TCC

3
.İn example.org normal bir ifade olduğu için herhangi bir değer olarak mı yorumlanıyor? Bu durumda, bu yanlışlıkla özel bir örnek-kuruluş TLD'sine izin verir mi?
stuckj

1
Doğru bir regex, "^example\.org$"bir bilgisayar korsanının subdomainexample.org^example.orgevil$examplezorg\.
regex'inizden

27

AJAX tarafından talep edilen bir PHP uygulaması için ne yaptım

$request_headers        = apache_request_headers();
$http_origin            = $request_headers['Origin'];
$allowed_http_origins   = array(
                            "http://myDumbDomain.example"   ,
                            "http://anotherDumbDomain.example"  ,
                            "http://localhost"  ,
                          );
if (in_array($http_origin, $allowed_http_origins)){  
    @header("Access-Control-Allow-Origin: " . $http_origin);
}

İstekte bulunan kaynağa sunucum tarafından izin veriliyorsa, joker karakter döndürmek yerine $http_originkendisini Access-Control-Allow-Originüstbilginin değeri olarak *döndürün.


20

Bilmeniz gereken bir dezavantaj vardır: Dosyaları bir CDN'ye (veya komut dosyasına izin vermeyen başka bir sunucuya) dışarı aktarır göndermez veya dosyalarınız bir proxy üzerinde önbelleğe alınırsa, 'Origin' kaynağına göre yanıt değiştirilir istek başlığı çalışmaz.


4
Bu konuyu biraz açıklayabilir misiniz veya daha fazla bilgi arayabileceğimiz bir yere yönlendirebilir misiniz? Bunu sadece Limelight ile yapmak istiyorum ve umarım yanılıyorsun. Teknik uzmanlarımızdan biri, CDN tohum sunucumuz başlığı gönderdiği sürece, CDN'nin kendisini göndereceğini söyledi. Henüz test
BT

12
Önbellekler veya CDN'ler endişe kaynağıysa, önbellek / CDN'ye farklı Origin istek başlığı değerleri için ayrı yanıtlar vermesini bildirmek için Vary üstbilgisini kullanın. Yanıtınıza "Vary: Origin" gibi bir başlık eklersiniz. : Önbellek / CDN o zaman başlık "Menşe ile bir isteğe bir yanıt göndermesi gerektiğini bilir foo.example.com başlığı": Menşe ile bir talebe ve farklı bir tepki " bar.example.com ".
Sean

Vary: Origin en büyük CDN'lerden biri olan Akamai tarafından desteklenmiyor ... Daha fazla detay burada da mevcut
Brad Parks

20

Birden çok etki için, Gözlerinde farklı .htaccess:

<IfModule mod_headers.c>
    SetEnvIf Origin "http(s)?://(www\.)?(domain1.example|domain2.example)$" AccessControlAllowOrigin=$0$1
    Header add Access-Control-Allow-Origin %{AccessControlAllowOrigin}e env=AccessControlAllowOrigin
    Header set Access-Control-Allow-Credentials true
</IfModule>

4
Bu pasaj benim için mükemmel çalışıyor. Ama ne yaptığını anlamıyorum: D
Karl Adler

2
'^' yani ... SetEnvIf Origin "^ http (s)
?:

Stackoverflow.com/a/14034228/209139 ile hemen hemen aynı şeyi yapar . Sadece .htaccess sözdizimini okumak PHP'den çok daha zordur. Header set Vary Originbu cevaba güzel bir ek olacaktır.
TRiG

1
Yardımınız için çok teşekkürler
Cool Perfectionist

2
Ben değiştirmek zorunda AccessControlAllowOrigin=$0$1için AccessControlAllowOrigin=$0. Aksi takdirde, HTTPS kökenleri için çalışmadı. http://example.comDoğru çıktı ama https://example.comolarak çıktı https://example.comsbir ekstralarla, sucunda.
TRiG

17

Nginx kullanıcılarının birden fazla alan için CORS'ye izin vermesi. @ Marshall'ın örneğini beğendim, ancak anwers'ı sadece bir alanla eşleşiyor. Alan adı ve alt alan adı listesiyle eşleştirmek için bu normal ifade yazı tipleriyle çalışmayı kolaylaştırır:

location ~* \.(?:ttf|ttc|otf|eot|woff|woff2)$ {
   if ( $http_origin ~* (https?://(.+\.)?(domain1|domain2|domain3)\.(?:me|co|com)$) ) {
      add_header "Access-Control-Allow-Origin" "$http_origin";
   }
}

Bu, yalnızca belirtilen alan adları listesiyle eşleşen "Access-Control-Allow-Origin" başlıklarını yankılandıracaktır.


Sonunda bu normal ifadeyi \ z ile kilitlemeniz gerektiğini düşünün, aksi takdirde domain3.com.badhacker.com'a erişim izni verilir.
dft

@dft Bunu sonunda $ olarak tanımlıyoruz
Adriano Rosa

Özür dilerim, öz örnekte kastediyorum, @AdrianoRosa'nın gerçek gönderisi
dft


13

İşte Java web uygulaması için yesthatguy'un cevabını temel alan bir çözüm.

Jersey REST 1.x kullanıyorum

Web.xml dosyasını Jersey REST ve CORSResponseFilter öğelerinden haberdar olacak şekilde yapılandırın

 <!-- Jersey REST config -->
  <servlet>    
    <servlet-name>JAX-RS Servlet</servlet-name>
    <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
    <init-param> 
        <param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name>
        <param-value>true</param-value>
    </init-param>
    <init-param>
      <param-name>com.sun.jersey.spi.container.ContainerResponseFilters</param-name>
      <param-value>com.your.package.CORSResponseFilter</param-value>
    </init-param>   
    <init-param>
        <param-name>com.sun.jersey.config.property.packages</param-name>
        <param-value>com.your.package</param-value>
    </init-param>        
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>JAX-RS Servlet</servlet-name>
    <url-pattern>/ws/*</url-pattern>
  </servlet-mapping>

İşte CORSResponseFilter kodu

import com.sun.jersey.spi.container.ContainerRequest;
import com.sun.jersey.spi.container.ContainerResponse;
import com.sun.jersey.spi.container.ContainerResponseFilter;


public class CORSResponseFilter implements ContainerResponseFilter{

@Override
public ContainerResponse filter(ContainerRequest request,
        ContainerResponse response) {

    String[] allowDomain = {"http://localhost:9000","https://my.domain.example"};
    Set<String> allowedOrigins = new HashSet<String>(Arrays.asList (allowDomain));                  

    String originHeader = request.getHeaderValue("Origin");

    if(allowedOrigins.contains(originHeader)) {
        response.getHttpHeaders().add("Access-Control-Allow-Origin", originHeader);

        response.getHttpHeaders().add("Access-Control-Allow-Headers",
                "origin, content-type, accept, authorization");
        response.getHttpHeaders().add("Access-Control-Allow-Credentials", "true");
        response.getHttpHeaders().add("Access-Control-Allow-Methods",
                "GET, POST, PUT, DELETE, OPTIONS, HEAD");
    }

    return response;
}

}

Yukarıdaki Bağlantı Süresi Doldu, yeni bir tane ekleyebilir veya daha fazla ayrıntı ile yanıtı güncelleyebilir misiniz, Teşekkürler
RajKumar Samala

Daha fazla ayrıntı ekledim, umarım bu yardımcı olur
duvo

12

Yukarıda belirtildiği gibi, Access-Control-Allow-Originbenzersiz olmalı veVary olmalıOrigin bir CDN'nin (İçerik Dağıtım Ağı) arkasındaysanız olarak ayarlanmalıdır .

Nginx yapılandırmamın ilgili kısmı:

if ($http_origin ~* (https?://.*\.mydomain.example(:[0-9]+)?)) {
  set $cors "true";
}
if ($cors = "true") {
  add_header 'Access-Control-Allow-Origin' "$http_origin";
  add_header 'X-Frame-Options' "ALLOW FROM $http_origin";
  add_header 'Access-Control-Allow-Credentials' 'true';
  add_header 'Vary' 'Origin';
}

sahiptir set $corsgizli anlam çeşit ya da cihazınız conifg sadece özgüdür? ikinci ile birlikte atlanabilir gibi görünüyorif
mikezter

Bu doğru, başlıkları ayarlamak için test ettiğiniz tek koşul bu değilse, atlanabilir, benim yapılandırmada çoklu vardı.
hernvnc

9

Belki yanılıyorum, ama görebildiğim kadarıyla Access-Control-Allow-Originbir "origin-list"as parametresi var.

Tarafından tanımı bir origin-listolduğu:

origin            = "origin" ":" 1*WSP [ "null" / origin-list ]
origin-list       = serialized-origin *( 1*WSP serialized-origin )
serialized-origin = scheme "://" host [ ":" port ]
                  ; <scheme>, <host>, <port> productions from RFC3986

Ve bundan farklı kökenlerin kabul edildiğini ve boşlukla ayrılması gerektiğini savunuyorum .


2
Bu, spesifikasyonun doğru bir yorumu gibi görünüyor; Bununla birlikte, spec mevcut tarayıcılar tarafından tam olarak desteklenmiyor gibi görünüyor (örneğin, bunu sadece Firefox 17.0'da test ettim ve çalışmayacağını doğruladım).
Rick Riensche

7
CORS spesifikasyon bölümü 5.1 Access-Control-Allow-Origin Response Headerkökenli listesi kısıtlı olduğu durumları: Aksine kökenli bir boşluk koyarak izin vermek yerine, ya tek bir kaynaktan ya da tel "boş" dir.
maxpolk

2
Kendi cevabımla ilgili bir yorumda belirttiğim gibi, bu bir RFC 2119 şartı değil, uygulayıcı notunun bir parçası. 'Doğru' cevap kesinlikle boşlukla sınırlandırılmış değerleri kullanmaktır. Sorun basitçe uygulamaların eksik olmasıdır ve bu nedenle 'doğru' cevap mutlaka işe yaramaz. Olmalı, ama değil. Ancak, gelecekte, uygulamalar daha iyi hale geldikçe, bu değişebilir.
Bob Aman

8

ExpressJS uygulamaları için şunları kullanabilirsiniz:

app.use((req, res, next) => {
    const corsWhitelist = [
        'https://domain1.example',
        'https://domain2.example',
        'https://domain3.example'
    ];
    if (corsWhitelist.indexOf(req.headers.origin) !== -1) {
        res.header('Access-Control-Allow-Origin', req.headers.origin);
        res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept');
    }

    next();
});

Bu bir sonraki çağrı ile diğer tüm çağrılara izin verecek ...
Ievgen Naida

@IevgenNaida Peki? Sorun nedir?
eyecatchUp

7

HTTPS çalıştıran bir alan adı için bunu ayarlamaya çalıştım, bu yüzden çözümü paylaşacağımı düşündüm. Httpd.conf dosyamda şu yönergeyi kullandım :

    <FilesMatch "\.(ttf|otf|eot|woff)$">
            SetEnvIf Origin "^http(s)?://(.+\.)?example\.com$" AccessControlAllowOrigin=$0
            Header set Access-Control-Allow-Origin %{AccessControlAllowOrigin}e env=AccessControlAllowOrigin
    </FilesMatch>

Değişiklik example.comAlan adınızla . Bunu httpd.conf dosyanıza <VirtualHost x.x.x.x:xx>ekleyin . Senin eğer Bildirimi bir liman eki (örn vardır ) ayrıca gitmek gerekir bu yüzden o zaman bu yönerge, HTTPS için geçerli olmayacaktır / etc / apache2 / sites-available / default-SSL ve söz konusu dosyanın, iç aynı yönergesini ekleyin ...VirtualHost:80<VirtualHost _default_:443> bölümü.

Yapılandırma dosyaları güncellendiğinde, terminalde aşağıdaki komutları çalıştırmanız gerekir:

a2enmod headers
sudo service apache2 reload

Bu seçeneği beğendim ve @George'un sahip olduğu uygulama ile birleştirdim / değiştirdim. Bazen sunucularda a2enmod bulunmaz, bu yüzden yapmanız gereken tek şey ana httpd.conf komutunu kontrol etmek.
Mike Kormendy

Benim kökeni bir bağlantı noktası numarası vardı, bu yüzden bunu dahil etmek için düzenli ifade değiştirdi: ^http(s)?://(.+\.)?example\.com(:\d+)?$
indiv

5

Yazı tipleriyle ilgili sorun yaşıyorsanız şunu kullanın:

<FilesMatch "\.(ttf|ttc|otf|eot|woff)$">
    <IfModule mod_headers>
        Header set Access-Control-Allow-Origin "*"
    </IfModule>
</FilesMatch>

3

Daha esnek bir yaklaşım Apache 2.4'ün ifadelerini kullanmaktır. Etki alanlarıyla, yollarla ve hemen hemen her istek değişkeniyle eşleşebilirsiniz. Gönderilen yanıt her zaman olsa da *, onu alan tek istekler yine de gereksinimleri karşılayanlardır. Kullanımı Origin(veya başka) ifade istek başlık otomatik olarak birleştirmek için Apache'nin Varybu yanıt farklı orjinli için tekrar olmayacak şekilde, tepki başlığı.

<IfModule mod_headers.c>
    <If "%{HTTP:Host} =~ /\\bcdndomain\\.example$/i && %{HTTP:Origin} =~ /\\bmaindomain\\.example$/i">
        Header set Access-Control-Allow-Origin "*"
    </If>
</IfModule>

2
Buraya geldim çünkü bazı tarayıcılar *Login gibi kimlik bilgilerini kabul etmiyor . Bu nedenle, eşleşen ana bilgisayar adını yerine geçmeniz daha iyi olacaktır *.
KeitelDOG

@KeitelDOG Her bir alan için kodu tekrarlamak yerine, doğru başlangıç ​​noktası dinamik olarak nasıl yakalanır ve birden fazla kaynak olduğunda geri gönderilir? O gibi görünüyor olabilir ifadelerle mümkün olabilir ama dokümanlar bana temizlemek değildir.
Walf

Laravel dönmedi çünkü Aslında benim gerçek sorunu olduğunu Access-Control-Allow-Originiçin başlık OPTIONSsunucusu bu orijinini izin verirse başlıklarını denetler görmek için bu uçuş öncesi isteği. Düzelttim. Yani *benim için asıl sorun değildi. Ama, yine de bazı tarayıcılar kabul etmiyoruz *Web App Çapraz Kökeni isteği göndererek zaman bu kadar, onlar belirtmek ZORUNDA, kimlik bilgileriyle HTTP_ORIGINdeğişkene sahip dinamik erişmek olabileceğini başlık Originiçinde .htaccessApache için veya $_SERVER['HTTP_ORIGIN'];PHP'de. Her neyse, çözümünüz tüm kökenlere izin verdiği için iyidir, ancak daha az güvenli
KeitelDOG

Ama hatırlanması gereken 2 şey var 1) sağlamak *her şeye izin verir. 2) HOST, ORIGIN'den farklı. HOST, istek üstbilgisine iletilen gerçek 'TARGET HOST'. Ancak ORIGIN INITIAL HOSTisteği gönderir TARGET HOST. Bu nedenle kodunuzda ORIGIN HOSTyok sayılır ve hiç kullanılmaz. Yukarıdaki yanıtlara bakın ve ORIGINonları eklemek için değerleri nasıl kullandıklarını göreceksiniz Access-Control-Allow-Origin.
KeitelDOG

@KeitelDOG İfadede istek üstbilgisinin *kullanılması, OriginApache'nin Vary, kullanmadıkça req_novary('Origin')(büyük olasılıkla istenmeyen) otomatik olarak yanıt üstbilgisiyle birleştirilmesine neden olduğu için herkese izin vermez . Tarayıcılar, farklı bir yanıt için farklı bir yanıt alabileceklerini bilirler Originve gönderilen değer bir kişinin testini geçemezse, Access-Control-Allow-Originbaşlık asla ayarlanmaz.
Walf

3

PHP Kodu:

$httpOrigin = isset($_SERVER['HTTP_ORIGIN']) ? $_SERVER['HTTP_ORIGIN'] : null;
if (in_array($httpOrigin, [
    'http://localhost:9000', // Co-worker dev-server
    'http://127.0.0.1:9001', // My dev-server
])) header("Access-Control-Allow-Origin: ${httpOrigin}");
header('Access-Control-Allow-Credentials: true');

2

HTTP_ORIGIN tüm tarayıcılar tarafından kullanılmaz. HTTP_ORIGIN ne kadar güvenli? Benim için FF'de boş çıkıyor.
Bir site kimliği üzerinden siteme erişim izni verdiğim siteler var, daha sonra bu kimliğe sahip kayıt için DB'mi kontrol ediyorum ve SITE_URL sütun değerini (www.yoursite.com) alıyorum.

header('Access-Control-Allow-Origin: http://'.$row['SITE_URL']);

Geçerli bir site kimliği üzerinden gönderme isteği, DB'de listelenen ve bu site kimliğiyle ilişkili alan adından olmalıdır.


2

Apache için en yeni ve planlanan yazı tipi tanımlarından bazılarını içeren genişletilmiş bir seçenek:

<FilesMatch "\.(ttf|otf|eot|woff|woff2|sfnt|svg)$">
    <IfModule mod_headers.c>
        SetEnvIf Origin "^http(s)?://(.+\.)?(domainname1|domainname2|domainname3)\.(?:com|net|org)$" AccessControlAllowOrigin=$0$1$2
        Header add Access-Control-Allow-Origin %{AccessControlAllowOrigin}e env=AccessControlAllowOrigin
        Header set Access-Control-Allow-Credentials true
    </IfModule>
</FilesMatch>

2

Bir ASMX hizmeti için birden çok etki alanı erişimini kolaylaştırmak için, global.asax dosyasında bu işlevi oluşturdum:

protected void Application_BeginRequest(object sender, EventArgs e)
{
    string CORSServices = "/account.asmx|/account2.asmx";
    if (CORSServices.IndexOf(HttpContext.Current.Request.Url.AbsolutePath) > -1)
    {
        string allowedDomains = "http://xxx.yyy.example|http://aaa.bbb.example";

        if(allowedDomains.IndexOf(HttpContext.Current.Request.Headers["Origin"]) > -1)
            HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", HttpContext.Current.Request.Headers["Origin"]);

        if(HttpContext.Current.Request.HttpMethod == "OPTIONS")
            HttpContext.Current.Response.End();
    }
}

Bu, CORS'in OPTIONSfiilin işlenmesine de izin verir .


2

Alt alan adlarını eşleştirmek için PHP kodu örneği.

if( preg_match("/http:\/\/(.*?)\.yourdomain.example/", $_SERVER['HTTP_ORIGIN'], $matches )) {
        $theMatch = $matches[0];
        header('Access-Control-Allow-Origin: ' . $theMatch);
}

2

.NET uygulamaları için oldukça kolay bir kopyalama / yapıştırma için, bunu CORS'u bir global.asax dosyadan . Bu kod, şu anda kabul edilen cevapta verilen tavsiyeyi izler ve talepteki geri dönüşün ne olduğunu geri gönderir. Bu, kullanmadan etkin bir şekilde '*' elde eder.

Bunun nedeni , 'withCredentials' özniteliği 'true' olarak ayarlanmış bir AJAX XMLHttpRequest gönderme yeteneği de dahil olmak üzere diğer birçok CORS özelliğini etkinleştirmesidir .

void Application_BeginRequest(object sender, EventArgs e)
{
    if (Request.HttpMethod == "OPTIONS")
    {
        Response.AddHeader("Access-Control-Allow-Methods", "GET, POST");
        Response.AddHeader("Access-Control-Allow-Headers", "Content-Type, Accept");
        Response.AddHeader("Access-Control-Max-Age", "1728000");
        Response.End();
    }
    else
    {
        Response.AddHeader("Access-Control-Allow-Credentials", "true");

        if (Request.Headers["Origin"] != null)
            Response.AddHeader("Access-Control-Allow-Origin" , Request.Headers["Origin"]);
        else
            Response.AddHeader("Access-Control-Allow-Origin" , "*");
    }
}

1

Ve Django'da bir cevap daha. Tek bir görünüme sahip olmak için birden çok alandan CORS izin vermek, İşte benim kod:

def my_view(request):
    if 'HTTP_ORIGIN' in request.META.keys() and request.META['HTTP_ORIGIN'] in ['http://allowed-unsecure-domain.com', 'https://allowed-secure-domain.com', ...]:
        response = my_view_response() # Create your desired response data: JsonResponse, HttpResponse...
        # Then add CORS headers for access from delivery
        response["Access-Control-Allow-Origin"] = request.META['HTTP_ORIGIN']
        response["Access-Control-Allow-Methods"] = "GET" # "GET, POST, PUT, DELETE, OPTIONS, HEAD"
        response["Access-Control-Max-Age"] = "1000"  
        response["Access-Control-Allow-Headers"] = "*"  
        return response

1

AWS Lambda / API Ağ Geçidi

Sunucusuz AWS Lambda ve API Ağ Geçidi üzerinde birden fazla kökenin nasıl yapılandırılacağı hakkında bilgi için - bir kişinin oldukça basit bir çözüm olmasına rağmen oldukça basit olması gerekir - buraya bakın:

https://stackoverflow.com/a/41708323/1624933


Şu anda API Ağ Geçidi'nde birden fazla kaynak yapılandırmak mümkün değildir, buraya bakın: https://docs.aws.amazon.com/apigateway/latest/developerguide/how-to-cors-console.html ), ancak öneri ( yukarıdaki cevap):

  • tarayıcı tarafından gönderilen Origin başlığını inceleyin
  • bir menşe beyaz listesine karşı kontrol et
  • eşleşiyorsa, gelen Kökeni Access-Control-Allow-Origin üstbilgisi olarak döndürün, aksi takdirde bir yer tutucu (varsayılan başlangıç ​​noktası) döndürün.

Basit çözüm açıkça ALL (*) 'u şu şekilde etkinleştirmektedir:

exports.handler = async (event) => {
    const response = {
        statusCode: 200,
        headers: {
            "Access-Control-Allow-Origin": "*",
            "Access-Control-Allow-Credentials" : true // Required for cookies, authorization headers with HTTPS
        },
        body: JSON.stringify([{

Ancak bunu API Ağ Geçidi tarafında yapmak daha iyi olabilir (yukarıdaki 2. bağlantıya bakın).


2
Access-Control-Allow-Credentials: truejoker karakterle izin verilmiyor Access-Control-Allow-Origin: *. <origin>Bunun yerine belirli bir ayar yapın .
Tom

@Tom, evet, neden orada olduğundan emin değilim, hatırlayamıyorum, ama AWS'ye eklenen varsayılanlardan kopyalamış olabilir miyim? Buna dikkat çektiğin için teşekkürler.
timhc22

0

Google'ın destek cevabı SSL üzerinden reklam sunmaya ve RFC kendisi dilbilgisi uzay URL'leri sınırlamak yapabilirsiniz belirtmek gibi görünüyor. Bunun farklı tarayıcılarda ne kadar iyi desteklendiğinden emin değilim.


'SSL üzerinden reklam sunma', w3.org/TR/cors/#access-control-allow-origin-response-header özelliğine bağlantı verir ve bu da "Uygulamada orijin listesi veya null üretimi daha kısıtlıdır
Boşlukla

Her ne kadar ayrıntı belirtmek önemli olsa da, bir spesifikasyon "Pratikte" dediği zaman, bunun sadece bu şekilde yapılmasının geçerli olduğu anlamına gelmez. Bu, bunu yaparsanız sorun yaşayabileceğiniz anlamına gelir çünkü uygulayıcıların çoğu spesifikasyonu yanlış veya eksik uygular. Spesifikasyon, burada EBNF'de aşağıdaki araçlarda görebileceğiniz, boşlukla ayrılmış bir orijin listesine izin verir origin-list: tools.ietf.org/html/rfc6454#section-7.1
Bob Aman

0

CORS kullanarak çalışmasını sağlamak için benim gibi çok sayıda kod örneği denerseniz, gerçekten çalışıp çalışmadığını denemek için önce önbelleğinizi temizlemeniz gerektiğini belirtmek gerekir. sunucuda silindi (çünkü hala önbelleğinize kaydedildi).

Örneğin CTRL + SHIFT + DELönbelleğinizi silmek için Google Chrome'da.

Bu, birçok saf .htaccessçözümü denedikten sonra bu kodu kullanmama yardımcı oldu ve bu tek çalışan gibiydi (en azından benim için):

    Header add Access-Control-Allow-Origin "http://google.com"
    Header add Access-Control-Allow-Headers "authorization, origin, user-token, x-requested-with, content-type"
    Header add Access-Control-Allow-Methods "PUT, GET, POST, DELETE, OPTIONS"

    <FilesMatch "\.(ttf|otf|eot|woff)$">
        <IfModule mod_headers.c>
            SetEnvIf Origin "http(s)?://(www\.)?(google.com|staging.google.com|development.google.com|otherdomain.com|dev02.otherdomain.net)$" AccessControlAllowOrigin=$0
            Header add Access-Control-Allow-Origin %{AccessControlAllowOrigin}e env=AccessControlAllowOrigin
        </IfModule>
    </FilesMatch>

Ayrıca yaygın birçok çözümleri yazmak zorunda söylüyorlar yayılır unutmayın Header set ...ama öyle Header add .... Umarım bu benim gibi birkaç saat boyunca aynı sıkıntılara sahip birine yardımcı olur.


0

Aşağıdaki cevap C # 'a özgüdür, ancak kavram tüm farklı platformlar için geçerli olmalıdır.

Bir web API'sından Çapraz Kaynak İsteklerine izin vermek için, Uygulamanıza Seçenek isteklerine izin vermeniz ve denetleyici düzeyinde aşağıda ek açıklama eklemeniz gerekir.

[EnableCors (UrlString, Header, Method)] Artık orijinler yalnızca dize olarak geçirilebilir. Yani istekte birden fazla URL iletmek istiyorsanız virgülle ayrılmış değer olarak iletin.

UrlString = " https: //a.hello.com,https: //b.hello.com "


0

Access-Control-Allow-Origin üstbilgisi için yalnızca tek bir kaynak belirtilebilir. Ancak isteğinize göre yanıtınızdaki kaynağı ayarlayabilirsiniz. Ayrıca Vary üstbilgisini ayarlamayı da unutmayın. PHP'de aşağıdakileri yaparım:

    /**
     * Enable CORS for the passed origins.
     * Adds the Access-Control-Allow-Origin header to the response with the origin that matched the one in the request.
     * @param array $origins
     * @return string|null returns the matched origin or null
     */
    function allowOrigins($origins)
    {
        $val = $_SERVER['HTTP_ORIGIN'] ?? null;
        if (in_array($val, $origins, true)) {
            header('Access-Control-Allow-Origin: '.$val);
            header('Vary: Origin');

            return $val;
        }

        return null;
    }

  if (allowOrigins(['http://localhost', 'https://localhost'])) {
      echo your response here, e.g. token
  }

-2

Bunu Asp.net uygulaması için Global.asax dosyasında da ayarlayabiliriz.

protected void Application_BeginRequest(object sender, EventArgs e)
    {

    // enable CORS
    HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", "https://www.youtube.com");

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