Access-Control-Allow-Origin Multiple Origin Domains?

1049

Apakah ada cara untuk mengizinkan beberapa domain silang menggunakan Access-Control-Allow-Originheader?

Saya sadar akan hal itu *, tetapi terlalu terbuka. Saya benar-benar ingin mengizinkan hanya beberapa domain.

Sebagai contoh, sesuatu seperti ini:

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

Saya sudah mencoba kode di atas tetapi sepertinya tidak berfungsi di Firefox.

Apakah mungkin untuk menentukan beberapa domain atau saya terjebak hanya dengan satu domain?

Thomas J Bradley
sumber
3
Menggunakan Firefox terbaru, tidak ada koma yang dipisah, atau domain yang dipisahkan ruang tidak berfungsi. Menyesuaikan dengan daftar domain dan menempatkan satu host di header adalah keamanan yang lebih baik dan bekerja dengan baik.
Daniel W.
1
Jika Anda berjuang dengan ini untuk HTTPS, saya menemukan solusinya .
Alex W
7
catatan penting : hanya mengizinkan domain cretain diAccess-Control-Allow-Originheader tidak berarti bahwa domain lain tidak dapat memicu metode pada titik akhir ini (mis. metode REST API). Ini hanya berarti bahwa asal yang dibolehkan tidak dapat menggunakan hasil dalam javascript (browser memastikan ini). Untuk membatasi akses ke titik akhir untuk domain tertentu gunakan filter permintaan sisi server yang misalnya mengembalikan HTTP 401 untuk domain yang tidak diizinkan.
klues
1
Anda harus selalu menambahkan Vary: Origintajuk saat Anda ingin menggunakan beberapa URL, lihat: fetch.spec.whatwg.org/#cors-protocol-and-http-caches
Null

Jawaban:

861

Kedengarannya seperti cara yang disarankan untuk melakukannya adalah meminta server Anda membaca header Asal dari klien, membandingkannya dengan daftar domain yang ingin Anda izinkan, dan jika cocok, gema nilai Originheader kembali ke klien sebagai yang Access-Control-Allow-Originheader respon.

Dengan .htaccessAnda dapat melakukannya seperti ini:

# ----------------------------------------------------------------------
# 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>
yesthatguy
sumber
41
Ini sesuai dengan apa yang disarankan oleh W3C - w3.org/TR/cors/#access-control-allow-origin-response-hea
Simon B.
153
Masalah saya dengan jawaban ini adalah itu tidak benar-benar membantu saya, karena kami menggunakan CDN, dan jelas kami tidak dapat mengontrol bagaimana CDN mengatur header secara programatik.
BT
6
Contoh aktual (Nginx) dalam jawaban saya di bawah ini - stackoverflow.com/a/12414239/6084
mjallday
71
Jika cache atau CDN merupakan masalah, gunakan header Vary untuk memberitahu cache / CDN untuk menjaga tanggapan terpisah untuk nilai header permintaan Asal yang berbeda. Anda akan menyertakan tajuk seperti "Vary: Origin" dalam respons Anda. Cache / CDN kemudian mengetahui bahwa ia harus mengirim satu respons ke permintaan dengan tajuk "Origin: foo.example.com ", dan respons yang berbeda terhadap permintaan dengan tajuk "Origin: bar.example.com ".
Sean
10
@saturdayplace, jika Anda memiliki akses ke header Asal, Anda sudah melewati CORS.
Paul Draper
222

Solusi lain yang saya gunakan di PHP:

$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");
}
Nikolay Ivanov
sumber
12
Mengapa tidak menggunakan pendekatan yang disarankan di stackoverflow.com/a/1850482/11635 [dan jangan mengirim wildcard, hanya asal yang diminta]? Ini hanya lebih permisif tanpa mencapai apa pun?
Ruben Bartelink
15
Memiliki header('Access-Control-Allow-Origin: *')kadang - kadang mengatakan tidak dapat menggunakan kartu liar jika bendera kredensial benar - terjadi ketika header('Access-Control-Allow-Credentials: true')mungkin. Jadi, lebih baik Izinkan-Asal $http_originitu sendiri jika persyaratannya terpenuhi
Rakib
6
ganti baris terakhir dengan header("Access-Control-Allow-Origin: " . $http_origin);untuk membuatnya berfungsi
François Romain
2
Kode ini tampak cacat, karena jika tidak ada tajuk HTTP_ORIGIN yang dikenali, tidak ada Akses-Kontrol-Bolehkan-Asal disetel sama sekali, biarkan skrip terbuka lebar.
Stephen R
9
@StephenR sebenarnya "tertutup lebar" akan lebih akurat, karena tujuan dari ini adalah untuk membuka skrip ke domain lain;)
Kaddath
113

Ini bekerja untuk saya:

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

Saat dimasukkan .htaccess, pasti akan berhasil.

Jay Dave
sumber
24
solusi terbaik untuk saya, tetapi saya menambahkan dukungan port (mis. localhost: 3000 untuk pengembangan): SetEnvIf Origin "^ http (s)?: // (. + \.)? (localhost | stackoverflow.com | example1.com) ( : [0-9] +)? $ "Origin_is = $ 0
vszurma
2
Dari beberapa jawaban di sekitar stackoverflow, inilah yang bekerja.
Meetai.com
Saya perlu menambahkan Header set Access-Control-Allow-Credentials trueini agar berfungsi seperti jawaban @ George
99 Masalah - Sintaksis bukan
Ini bekerja dengan pasti ketika saya menggunakan Origin. Tetapi dalam beberapa kasus, Origin tidak tersedia dalam beberapa permintaan dan itu juga spesifik browser. Kemudian, saya memutuskan untuk menggunakan Refererbukan Origin. Menggunakan Refererkarya tetapi masalahnya adalah mengatur URL lengkap kembali ke Access-Control-Allow-OriginSaya ingin memotong nama domain Refererdan menugaskannya Access-Control-Allow-Origin. Sesuatu seperti hasil ini - echo http://example.com/index.php/ab/cd | cut -d'/' -f1,2,3dalam perintah bash. Apakah ini mungkin untuk melakukan hal yang sama pada file conf (apache)? Ada ide?
3AK
1
Ini tidak berhasil untuk saya. Selalu memiliki kesalahan kode 500 ketika saya menambahkan 2 baris. Sebenarnya menggunakan PHP 5.6.15
BoCyrill
91

Saya memiliki masalah yang sama dengan font-woff, beberapa subdomain harus memiliki akses. Untuk mengizinkan subdomain saya menambahkan sesuatu seperti ini ke httpd.conf saya:

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>

Untuk beberapa domain, Anda cukup mengubah regex di SetEnvIf.

Staugaard
sumber
4
Lakukan triknya. Pastikan Anda mengadaptasi ekspresi reguler dengan benar. Saya perlu menambahkan tanda tanya untuk memungkinkan domain itu sendiri, misalnya (.*\.?example\.org)untuk example.comdan sub.example.com.
trkoch
3
Adakah pemikiran tentang bagaimana mengadaptasi ini untuk IIS 7?
Tandai
Bukankah itu mengalahkan tujuannya? Apa yang akan mencegah pengguna jahat dari menempa nilai header Asal?
Grégory Joseph
1
@ GrégoryJoseph Access-Control-Allow-Origin bukan tentang menyembunyikan sumber daya dari seseorang yang dapat memintanya. Ini tentang mencegah situs jahat agar pengguna akhir memanggil situs Anda. Dalam hal file font, ini hanya dapat secara efektif membatasi tautan hot font, mengapa mereka (mozilla / firefox) tidak melakukan hal yang sama untuk sumber daya lain (js, css, dll) berada di luar jangkauan saya.
Tracker1
@trkoch, ada bug di regex Anda, itu juga akan memungkinkan subexample.com. Anda harus mengubahnya ke:((.*\.)?example\.org)
bluesmoon
65

Berikut ini cara mengulang kembali header Asal jika cocok dengan domain Anda dengan Nginx, ini berguna jika Anda ingin menyajikan font beberapa sub-domain:

location /fonts {
    # this will echo back the origin header
    if ($http_origin ~ "example.org$") {
        add_header "Access-Control-Allow-Origin" $http_origin;
    }
}
mjallday
sumber
Tidak dapat memahami apa bedanya dengan: add_header Access-Control-Allow-Origin *; Mau jelaskan?
Anoyz
ini akan mengembalikan header yang mengizinkan browser untuk hanya mengirim permintaan dari domain yang ditentukan. jika saya kira saya akan mengatakan browser dapat mengotorisasi konten dari domain lain yang dimuat pada halaman itu untuk mengakses server sebaliknya.
mjallday
7
@Anoyz untuk satu hal mungkin ada peningkatan keamanan di mana "Izinkan *" tidak diizinkan, tetapi nama host yang ditentukan dan cocok untuk header memungkinkan bekerja. Contoh di sini, jika Anda ingin mengirim informasi lintas domain, Anda tidak dapat menggunakan "Izinkan *"
TCC
3
Apakah .in example.org diartikan sebagai nilai karena ini adalah ekspresi reguler? Dalam hal ini, apakah ini keliru akan memungkinkan TLD contoh-org kustom?
stuckj
1
Regex yang benar seharusnya "^example\.org$"karena Anda perlu memastikan seorang peretas tidak dapat menyelinap melalui regex Anda dengan subdomainexample.org(menggunakan ^) atau example.orgevil(menggunakan $) atau examplezorg(melarikan diri \.)
zeg
27

Inilah yang saya lakukan untuk aplikasi PHP yang diminta oleh AJAX

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

Jika asal yang diminta diizinkan oleh server saya, kembalikan $http_originsendiri sebagai nilai Access-Control-Allow-Origintajuk alih-alih mengembalikan *wildcard.

Rakib
sumber
20

Ada satu kelemahan yang harus Anda ketahui: Segera setelah Anda meng-out-source file ke CDN (atau server lain yang tidak mengizinkan skrip) atau jika file Anda di-cache pada proxy, mengubah respons berdasarkan 'Asal' header permintaan tidak akan berfungsi.

Menandai
sumber
4
Bisakah Anda menguraikan ini, atau mengarahkan kami ke suatu tempat kami dapat mencari info lebih lanjut? Saya ingin melakukan hal itu dengan Limelight, dan saya berharap Anda salah. Salah satu teknisi kami mengatakan bahwa selama server seed CDN kami mengirimkan header, CDN itu sendiri akan mengirimkannya. Belum mengujinya
BT
12
Jika cache atau CDN merupakan masalah, gunakan header Vary untuk memberitahu cache / CDN untuk menjaga tanggapan terpisah untuk nilai header permintaan Asal yang berbeda. Anda akan menyertakan tajuk seperti "Vary: Origin" dalam respons Anda. Cache / CDN kemudian mengetahui bahwa ia harus mengirim satu respons ke permintaan dengan tajuk "Origin: foo.example.com ", dan respons yang berbeda terhadap permintaan dengan tajuk "Origin: bar.example.com ".
Sean
Vary: Origin tidak didukung oleh Akamai , salah satu CDN terbesar di luar sana ... Lebih detail juga tersedia di sini
Brad Parks
20

Untuk banyak domain, di .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>
George
sumber
4
Cuplikan ini sangat cocok untuk saya. Tapi saya tidak mengerti apa fungsinya: D
Karl Adler
2
ini bekerja untuk saya, walaupun saya harus menambahkan '^' yaitu ... SetEnvIf Asal "^ http (s)?: // (www \.)?
gypsyDev
Itu hampir sama dengan stackoverflow.com/a/14034228/209139 . Hanya saja sintaks .htaccess jauh lebih sulit dibaca daripada PHP. Header set Vary Originakan menjadi tambahan yang bagus untuk jawaban ini.
TRiG
1
Terima kasih banyak atas bantuan Anda
Cool Perfeksionis
2
Saya harus pindah AccessControlAllowOrigin=$0$1ke AccessControlAllowOrigin=$0. Kalau tidak, itu tidak berfungsi untuk asal HTTPS. http://example.comkeluar dengan benar, tetapi https://example.comkeluar sebagai https://example.coms, dengan tambahan sdi akhir.
TRiG
17

Untuk pengguna Nginx untuk memungkinkan CORS untuk banyak domain. Saya suka contoh @ marshall meskipun jawaban hanya cocok dengan satu domain. Untuk mencocokkan daftar domain dan subdomain regex ini membuatnya mudah untuk bekerja dengan font:

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

Ini hanya akan menggemakan tajuk "Akses-Kontrol-Bolehkan-Asal" yang cocok dengan daftar domain yang diberikan.

Adriano Rosa
sumber
Pikirkan Anda perlu mengunci regex di bagian akhir dengan \ z karena jika tidak domain3.com.badhacker.com akan diizinkan mengakses.
dft
@dft Kami mendefinisikan $ di akhir yang melakukan itu
Adriano Rosa
Maaf yang saya maksudkan dalam contoh inti, posting aktual oleh @AdrianoRosa melakukan hal yang sama dengan \ z
dft
16

Untuk IIS 7.5+ dengan modul URL Rewrite 2.0 diinstal silakan lihat jawaban SO ini

Paco Zarate
sumber
13

Inilah solusi untuk aplikasi web Java, berdasarkan jawaban dari yesthatguy.

Saya menggunakan Jersey REST 1.x

Konfigurasikan web.xml untuk mengetahui Jersey REST dan CORSResponseFilter

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

Berikut kode untuk CORSResponseFilter

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

}
duvo
sumber
Above Link Kedaluwarsa, dapatkah Anda menambahkan yang baru, atau memperbarui jawaban dengan lebih jelas, Terima kasih
RajKumar Samala
Saya telah menambahkan lebih banyak detail, semoga ini membantu
duvo
12

Seperti disebutkan di atas, Access-Control-Allow-Originharus unik dan Varyharus ditetapkan Originjika Anda berada di belakang CDN (Jaringan Pengiriman Konten).

Bagian yang relevan dari konfigurasi Nginx saya:

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';
}
hernvnc
sumber
memiliki set $corssemacam makna tersembunyi, atau hanya khusus untuk conifg Anda? sepertinya itu bisa dihilangkan bersama dengan yang keduaif
mikezter
Itu benar, itu bisa dihilangkan jika itu satu-satunya syarat Anda menguji untuk mengatur header, saya punya banyak di konfigurasi saya.
hernvnc
9

Mungkin saya salah, tetapi sejauh yang saya bisa lihat Access-Control-Allow-Originmemiliki "origin-list"parameter sebagai.

Dengan definisi sebuah origin-listadalah:

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

Dan dari sini, saya berpendapat bahwa asal-usul yang berbeda diakui dan harus dipisahkan ruang .

drAlberT
sumber
2
Itu tampaknya merupakan interpretasi yang benar dari spec; yang mengatakan, spek sepertinya tidak sepenuhnya didukung oleh browser saat ini (misalnya, saya baru saja menguji ini pada Firefox 17.0 dan mengkonfirmasi bahwa itu tidak akan berfungsi).
Rick Riensche
7
The CORS Spesifikasi Bagian 5.1 Access-Control-Allow-Origin Response Headermenyatakan bahwa asal-list dibatasi: Daripada membiarkan daftar ruang yang dipisahkan dari asal-usul, itu adalah baik asal tunggal atau string "nol".
maksimal
2
Seperti yang saya sebutkan dalam komentar atas jawaban saya sendiri, itu bagian dari catatan implementor, bukan persyaratan RFC 2119. Jawaban yang benar adalah dengan menggunakan nilai-nilai yang dibatasi ruang. Masalahnya hanya karena implementasinya tidak lengkap dan jawaban 'benar' tidak selalu berhasil. Seharusnya, tetapi tidak. Namun, di masa depan, seiring implementasi yang semakin baik, ini dapat berubah.
Bob Aman
8

Untuk aplikasi ExpressJS Anda dapat menggunakan:

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();
});
eyecatchUp
sumber
ini akan memungkinkan semua panggilan lain dengan panggilan berikutnya ...
Ievgen Naida
@IevgenNaida Jadi? apa masalahnya?
eyecatchUp
7

Saya kesulitan mengatur ini untuk domain yang menjalankan HTTPS, jadi saya pikir saya akan membagikan solusinya. Saya menggunakan arahan berikut dalam file httpd.conf saya :

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

Ubah example.comnama domain Anda. Tambahkan ini di <VirtualHost x.x.x.x:xx>dalam file httpd.conf Anda . Perhatikan bahwa jika Anda VirtualHostmemiliki akhiran port (mis. :80) Maka arahan ini tidak akan berlaku untuk HTTPS, jadi Anda juga harus pergi ke /etc/apache2/situss available/ default-ssl dan tambahkan arahan yang sama dalam file itu, di dalamnya dari <VirtualHost _default_:443>bagian.

Setelah file konfigurasi diperbarui, Anda harus menjalankan perintah berikut di terminal:

a2enmod headers
sudo service apache2 reload
Alex W
sumber
Saya suka opsi ini dan menggabungkan / memodifikasinya dengan implementasi yang dimiliki @George. Terkadang server tidak memiliki a2enmod yang tersedia, jadi yang harus Anda lakukan adalah memeriksa httpd.conf utama Anda untuk melihat apakah baris: LoadModule headers_module modules / mod_headers.so tidak dikomandoi.
Mike Kormendy
Asal saya memiliki nomor port, jadi saya mengubah ekspresi reguler untuk memasukkan: ^http(s)?://(.+\.)?example\.com(:\d+)?$
indiv
5

Jika Anda mengalami masalah dengan font, gunakan:

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

Pendekatan yang lebih fleksibel adalah dengan menggunakan ekspresi Apache 2.4. Anda dapat mencocokkan dengan domain, jalur, dan hampir setiap variabel permintaan lainnya. Meskipun respons yang dikirim selalu *, hanya pemohon yang menerimanya yang memenuhi persyaratan. Menggunakan Origintajuk permintaan (atau yang lainnya) dalam ekspresi menyebabkan Apache untuk secara otomatis menggabungkannya ke Varytajuk respons, sehingga respons tidak akan digunakan kembali untuk asal yang berbeda.

<IfModule mod_headers.c>
    <If "%{HTTP:Host} =~ /\\bcdndomain\\.example$/i && %{HTTP:Origin} =~ /\\bmaindomain\\.example$/i">
        Header set Access-Control-Allow-Origin "*"
    </If>
</IfModule>
Walf
sumber
2
Saya datang ke sini karena beberapa browser tidak menerima *dengan kredensial seperti Login. Jadi akan lebih baik jika Anda melewatkan nama host yang cocok daripada *.
KeitelDOG
@KeitelDOG bagaimana cara secara dinamis menangkap asal yang benar dan mengirimkannya kembali ketika ada banyak asal, alih-alih mengulang kode untuk setiap domain? Sepertinya mungkin menjadi mungkin dengan ekspresi tetapi docs tidak jelas kepada saya.
Walf
Sebenarnya masalah saya yang sebenarnya adalah karena laravel tidak mengembalikan Access-Control-Allow-Originheader untuk OPTIONSpermintaan preflight yang memeriksa header untuk melihat apakah server mengizinkan asal ini. Saya sudah memperbaikinya. Jadi *bukan masalah sebenarnya bagi saya. Tapi, masih beberapa browser tidak menerima *dengan mandat, sehingga saat Aplikasi Web mengirimkan permintaan Cross-Origin, mereka HARUS menentukan HTTP_ORIGINheader yang mungkin Anda mengakses secara dinamis dengan variabel Origindi .htaccessuntuk Apache, atau $_SERVER['HTTP_ORIGIN'];PHP. Pokoknya solusi Anda baik karena memungkinkan semua asal, tetapi kurang aman
KeitelDOG
Tetapi 2 hal yang perlu diingat adalah bahwa 1) Menyediakan *memungkinkan segalanya. 2) HOST berbeda dari ASAL. HOST adalah 'TARGET HOST' yang sebenarnya yang dikirimkan ke header permintaan. Tapi ASLI adalah INITIAL HOSTyang mengirim permintaan ke TARGET HOST. Karenanya dalam kode Anda, ORIGIN HOSTdiabaikan dan tidak pernah digunakan. Lihat jawaban di atas dan Anda akan melihat bagaimana mereka menggunakan ORIGINnilai untuk menambahkannya Access-Control-Allow-Origin.
KeitelDOG
@KeitelDOG *Tidak mengizinkan semua orang karena menggunakan Origintajuk permintaan dalam ekspresi menyebabkan Apache untuk secara otomatis menggabungkannya ke Varytajuk respons, kecuali jika salah satu menggunakan req_novary('Origin')(kemungkinan tidak diinginkan). Peramban tahu bahwa mereka mungkin mendapatkan respons berbeda untuk yang berbeda Origindan jika nilai yang dikirim tidak lulus pengujian, Access-Control-Allow-Origintajuk itu tidak pernah disetel.
Walf
3

Kode PHP:

$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');
Liakos
sumber
2

HTTP_ORIGIN tidak digunakan oleh semua browser. Seberapa amankah HTTP_ORIGIN? Bagi saya itu muncul kosong di FF.
Saya memiliki situs yang saya izinkan akses ke situs saya mengirim melalui ID situs, saya kemudian memeriksa DB saya untuk catatan dengan id itu dan mendapatkan nilai kolom SITE_URL (www.yoursite.com).

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

Bahkan jika pengiriman melalui ID situs yang valid, permintaan harus dari domain yang tercantum dalam DB saya yang terkait dengan ID situs tersebut.

mathius1
sumber
2

Berikut adalah opsi yang diperluas untuk apache yang mencakup beberapa definisi font terbaru dan terencana:

<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>
Mike Kormendy
sumber
2

Untuk memfasilitasi beberapa akses domain untuk layanan ASMX, saya membuat fungsi ini di file global.asax:

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

Ini memungkinkan penanganan CORS untuk OPTIONSkata kerja juga.

Derek Wade
sumber
2

Contoh kode PHP untuk subdomain yang cocok.

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

Untuk copy / paste yang cukup mudah untuk aplikasi .NET, saya menulis ini untuk mengaktifkan CORS dari dalam global.asaxfile. Kode ini mengikuti saran yang diberikan dalam jawaban yang saat ini diterima, yang mencerminkan asal apa pun yang diberikan dalam permintaan ke dalam respons. Ini secara efektif mencapai '*' tanpa menggunakannya.

Alasannya adalah ini memungkinkan beberapa fitur CORS lainnya , termasuk kemampuan untuk mengirim AJAX XMLHttpRequest dengan atribut 'withCredentials' yang disetel ke 'true'.

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" , "*");
    }
}
QA Collective
sumber
1

Dan satu jawaban lagi di Django. Untuk memiliki satu tampilan memungkinkan CORS dari beberapa domain, berikut ini adalah kode saya:

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
Silvain
sumber
1

AWS Lambda / API Gateway

Untuk informasi tentang cara mengonfigurasi beberapa asal pada Serverless AWS Lambda dan API Gateway - meskipun solusi yang agak besar untuk sesuatu yang orang merasa harus cukup mudah - lihat di sini:

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


Saat ini tidak memungkinkan untuk mengonfigurasi beberapa asal di API Gateway, lihat di sini: https://docs.aws.amazon.com/apigateway/latest/developerguide/how-to-cors-console.html ), tetapi rekomendasinya (dalam jawaban di atas) adalah:

  • periksa header Asal yang dikirim oleh browser
  • periksa dengan daftar putih asal
  • jika cocok, kembalikan Origin yang masuk sebagai header Access-Control-Allow-Origin, kalau tidak kembalikan placeholder (asal default).

Solusi sederhana ini jelas mengaktifkan SEMUA (*) seperti:

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([{

Tetapi mungkin lebih baik untuk melakukan ini di sisi API Gateway (lihat tautan ke-2 di atas).

timhc22
sumber
2
Access-Control-Allow-Credentials: truetidak diperbolehkan dengan wildcard Access-Control-Allow-Origin: *. Tetapkan yang spesifik <origin>sebagai gantinya.
Tom
@ Tom, ya, tidak yakin mengapa itu ada di sana, saya tidak ingat, tapi saya mungkin telah menyalinnya dari default yang ditambahkan pada AWS? Terima kasih telah menunjukkannya.
timhc22
0

Dukungan Google menjawab pada penyajian iklan melalui SSL dan tata bahasa di RFC itu sendiri tampaknya menunjukkan bahwa Anda dapat membatasi ruang URL. Tidak yakin seberapa baik ini didukung di browser yang berbeda.

Bob Aman
sumber
tautan 'menayangkan iklan melebihi ssl' ke spec w3.org/TR/cors/#access-control-allow-origin-response-header yang menambahkan catatan, "Dalam praktiknya produksi asal-daftar-atau-nol lebih dibatasi. Daripada mengizinkan daftar asal-usul yang dipisahkan oleh ruang, itu adalah asal tunggal atau string "null".
spazm
Meskipun penting untuk mencatat detail itu, ketika spesifikasi mengatakan "Dalam praktek", itu tidak berarti bahwa itu hanya valid untuk melakukannya dengan cara itu. Ini berarti bahwa jika Anda melakukannya dengan cara itu, Anda dapat mengalami masalah karena mayoritas implementor mengimplementasikan spec secara salah atau tidak lengkap. Spesifikasi memang memungkinkan untuk daftar asal terpisah ruang, yang dapat Anda lihat di sini di EBNF di bawah origin-list: tools.ietf.org/html/rfc6454#section-7.1
Bob Aman
0

Jika Anda mencoba begitu banyak contoh kode seperti saya untuk membuatnya berfungsi menggunakan CORS, perlu disebutkan bahwa Anda harus menghapus cache terlebih dahulu untuk mencoba jika itu benar-benar berfungsi, mirip dengan masalah seperti ketika gambar lama masih ada, bahkan jika itu dihapus di server (karena masih disimpan dalam cache Anda).

Misalnya CTRL + SHIFT + DELdi Google Chrome untuk menghapus cache Anda.

Ini membantu saya menggunakan kode ini setelah mencoba banyak .htaccesssolusi murni dan ini sepertinya satu-satunya yang berfungsi (setidaknya bagi saya):

    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>

Perhatikan juga bahwa ini tersebar luas sehingga banyak solusi mengatakan Anda harus mengetik Header set ...tetapi memang demikian Header add .... Semoga ini bisa membantu seseorang yang memiliki masalah yang sama selama beberapa jam sekarang seperti saya.

AlexioVay
sumber
0

Jawaban di bawah ini khusus untuk C #, tetapi konsep tersebut harus berlaku untuk semua platform yang berbeda.

Untuk mengizinkan Permintaan Lintas Asal dari api web, Anda harus mengizinkan permintaan Opsi ke Aplikasi Anda dan Menambahkan anotasi di bawah pada tingkat pengontrol.

[EnableCors (UrlString, Header, Method)] Sekarang asal hanya dapat diteruskan sebagai string. JADI, jika Anda ingin mengirimkan lebih dari satu URL dalam permintaan, berikan sebagai nilai yang dipisah koma.

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

sakshi agrawal
sumber
0

Hanya satu sumber yang dapat ditentukan untuk header Access-Control-Allow-Origin. Tetapi Anda dapat mengatur asal dalam respons Anda sesuai dengan permintaan. Juga jangan lupa mengatur header Vary. Dalam PHP saya akan melakukan hal berikut:

    /**
     * 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
  }
Simon
sumber
-2

Kami juga dapat mengatur ini di file Global.asax untuk aplikasi Asp.net.

protected void Application_BeginRequest(object sender, EventArgs e)
    {

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

    }
sudhAnsu63
sumber