Pertanyaan Bagaimana cara kerja header Access-Control-Allow-Origin?


Rupanya, saya benar-benar salah memahami semantiknya. Saya memikirkan sesuatu seperti ini:

  1. Klien mengunduh kode javascript MyCode.js dari http: // siteA - asal.
  2. Header respons dari MyCode.js berisi Access-Control-Allow-Origin: http: // siteB, yang saya pikir berarti bahwa MyCode.js diizinkan untuk membuat referensi asal silang ke situs B.
  3. Klien memicu beberapa fungsi MyCode.js, yang pada gilirannya membuat permintaan ke http: // siteB, yang seharusnya baik-baik saja, meskipun ada permintaan lintas-asal.

Yah, saya salah. Itu tidak bekerja seperti ini sama sekali. Jadi, saya telah membaca Pembagian sumber daya lintas-asal dan berusaha membaca Pembagian Sumber Daya Lintas-Asal dalam rekomendasi w3c

Satu hal yang pasti - saya masih tidak mengerti bagaimana saya harus menggunakan header ini.

Saya memiliki kontrol penuh terhadap situs A dan situs B. Bagaimana cara mengaktifkan kode javascript yang diunduh dari situs A untuk mengakses sumber daya di situs B menggunakan tajuk ini?

P.S.

Saya tidak ingin menggunakan JSONP.


787
2018-05-17 13:23


asal


Jawaban:


Access-Control-Allow-Origin adalah Header CORS (Cross-Origin Resource Sharing).

Ketika Situs A mencoba mengambil konten dari Situs B, Situs B dapat mengirim Access-Control-Allow-Origin tajuk respons untuk memberi tahu browser bahwa konten laman ini dapat diakses oleh asal tertentu. (Sebuah asal adalah domain, ditambah skema dan nomor port.) Secara default, halaman Situs B adalah tidak dapat diakses ke asal lainnya; menggunakan Access-Control-Allow-Origin tajuk membuka pintu untuk akses lintas asal oleh asal yang meminta spesifik.

Untuk setiap sumber daya / halaman yang ingin Situs B dapat diakses ke Situs A, Situs B harus melayani halamannya dengan header tanggapan:

Access-Control-Allow-Origin: http://siteA.com

Browser modern tidak akan memblokir permintaan lintas domain secara langsung. Jika Situs A meminta halaman dari Situs B, browser akan benar-benar mengambil halaman yang diminta di tingkat jaringan dan periksa apakah header respons mencantumkan Situs A sebagai domain penuntut yang diizinkan. Jika Situs B tidak menunjukkan bahwa Situs A diizinkan untuk mengakses halaman ini, browser akan memicu XMLHttpRequest's error acara dan menolak data respons ke kode JavaScript yang meminta.

Permintaan yang tidak sederhana

Apa yang terjadi pada level jaringan bisa sedikit lebih kompleks dari yang dijelaskan di atas. Jika permintaannya adalah a permintaan "tidak sederhana", browser terlebih dahulu mengirim permintaan OPTION tanpa data "preflight", untuk memverifikasi bahwa server akan menerima permintaan tersebut. Permintaan tidak sederhana ketika (atau keduanya):

  • menggunakan kata kerja HTTP selain GET atau POST (mis. PUT, DELETE)
  • menggunakan header permintaan non-sederhana; satu-satunya tajuk permintaan sederhana adalah:
    • Accept
    • Accept-Language
    • Content-Language
    • Content-Type (ini hanya sederhana ketika nilainya application/x-www-form-urlencoded, multipart/form-data, atau text/plain)

Jika server merespons OPTIONS preflight dengan header respons yang sesuai (Access-Control-Allow-Headers untuk tajuk yang tidak sederhana, Access-Control-Allow-Methodsuntuk kata kerja non-sederhana) yang cocok dengan kata kerja non-sederhana dan / atau header yang tidak sederhana, maka browser mengirimkan permintaan yang sebenarnya.

Misalkan Situs A ingin mengirim permintaan PUT untuk /somePage, dengan yang tidak sederhana Content-Type Nilai dari application/json, peramban terlebih dahulu akan mengirim permintaan preflight:

OPTIONS /somePage HTTP/1.1
Origin: http://siteA.com
Access-Control-Request-Method: PUT
Access-Control-Request-Headers: Content-Type

Perhatikan itu Access-Control-Request-Method dan Access-Control-Request-Headers ditambahkan oleh browser secara otomatis; Anda tidak perlu menambahkannya. Pendahuluan OPTIONS ini mendapatkan header tanggapan yang berhasil:

Access-Control-Allow-Origin: http://siteA.com
Access-Control-Allow-Methods: GET, POST, PUT
Access-Control-Allow-Headers: Content-Type

Saat mengirim permintaan yang sebenarnya (setelah preflight selesai), perilaku identik dengan bagaimana permintaan sederhana ditangani. Dengan kata lain, permintaan non-sederhana yang preflight-nya berhasil diperlakukan sama dengan permintaan sederhana (yaitu, server masih harus mengirim Access-Control-Allow-Origin lagi untuk respon yang sebenarnya).

Browser mengirimkan permintaan yang sebenarnya:

PUT /somePage HTTP/1.1
Origin: http://siteA.com
Content-Type: application/json

{ "myRequestContent": "JSON is so great" }

Dan server mengirim kembali sebuah Access-Control-Allow-Origin, seperti halnya permintaan sederhana:

Access-Control-Allow-Origin: http://siteA.com

Lihat Memahami XMLHttpRequest over CORS untuk sedikit informasi lebih lanjut tentang permintaan yang tidak sederhana.


1020
2018-05-17 13:33



Pembagian Permintaan Lintas-Asal - CORS (A.K.A. Permintaan Cross-Domain AJAX) adalah masalah yang mungkin dihadapi sebagian besar pengembang web, sesuai dengan Kebijakan Asal-Sama, browser membatasi JavaScript klien dalam kotak pasir keamanan, biasanya JS tidak dapat langsung berkomunikasi dengan server jarak jauh dari domain yang berbeda. Di masa lalu, pengembang menciptakan banyak cara rumit untuk mencapai permintaan sumber daya Lintas Domain, yang paling sering menggunakan cara adalah:

  1. Gunakan Flash / Silverlight atau sisi server sebagai "proxy" untuk berkomunikasi dengan remote.
  2. JSON With Padding (JSONP).
  3. Sematkan server jarak jauh dalam iframe dan komunikasikan melalui fragmen atau window.name, lihat sini.

Cara-cara rumit tersebut memiliki lebih atau kurang beberapa masalah, misalnya JSONP mungkin menghasilkan lubang keamanan jika pengembang hanya "mengevaluasinya", dan # 3 di atas, meskipun berfungsi, kedua domain harus membangun kontrak yang ketat antara satu sama lain, tidak fleksibel atau elegan MENURUT OPINI SAYA:)

W3C telah memperkenalkan Cross-Origin Resource Sharing (CORS) sebagai solusi standar untuk menyediakan cara standar yang aman, fleksibel dan direkomendasikan untuk menyelesaikan masalah ini.

Mekanisme

Dari tingkat yang tinggi kita dapat dengan mudah menganggap CORS adalah kontrak antara panggilan AJAX klien dari domain A dan halaman yang dihosting di domain B, permintaan / tanggapan Cross-Origin yang khas adalah:

Header permintaan DomainA AJAX

Host DomainB.com
User-Agent Mozilla/5.0 (Windows NT 6.1; WOW64; rv:2.0) Gecko/20100101 Firefox/4.0
Accept text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8,application/json
Accept-Language en-us;
Accept-Encoding gzip, deflate
Keep-Alive 115
Origin http://DomainA.com 

Header respons DomainB

Cache-Control private
Content-Type application/json; charset=utf-8
Access-Control-Allow-Origin DomainA.com
Content-Length 87
Proxy-Connection Keep-Alive
Connection Keep-Alive

Bagian biru yang saya tandai di atas adalah fakta kernal, header permintaan "Origin" "menunjukkan di mana permintaan lintas-asal atau permintaan preflight berasal dari", header respons "Access-Control-Allow-Origin" menunjukkan halaman ini memungkinkan permintaan jauh dari DomainA (jika nilainya * mengindikasikan memungkinkan permintaan jauh dari domain mana pun).

Seperti yang saya sebutkan di atas, W3 merekomendasikan peramban untuk mengimplementasikan "permintaan preflight"sebelum mengajukan permintaan HTTP Cross-Origin sebenarnya, singkatnya itu adalah HTTP OPTIONS permintaan:

OPTIONS DomainB.com/foo.aspx HTTP/1.1

Jika foo.aspx mendukung OPTIONS HTTP verb, mungkin mengembalikan respons seperti di bawah ini:

HTTP/1.1 200 OK
Date: Wed, 01 Mar 2011 15:38:19 GMT
Access-Control-Allow-Origin: http://DomainA.com
Access-Control-Allow-Methods: POST, GET, OPTIONS, HEAD
Access-Control-Allow-Headers: X-Requested-With
Access-Control-Max-Age: 1728000
Connection: Keep-Alive
Content-Type: application/json

Hanya jika respons berisi "Access-Control-Allow-Origin" DAN nilainya adalah "*" atau berisi domain yang mengajukan permintaan CORS, dengan memenuhi browser ketentuan mandtory ini akan mengirimkan permintaan Cross-Domain yang sebenarnya, dan menyimpan hasilnya di "Preflight-Result-Cache".

Saya membuat blog tentang CORS tiga tahun lalu: Permintaan HTTP Cross-Origin AJAX


102
2018-01-23 13:54



Pertanyaan agak terlalu lama untuk dijawab, tetapi saya memposting ini untuk referensi apa pun di masa mendatang untuk pertanyaan ini.

Menurut ini Artikel Pengembang Jaringan Mozilla,

Sumber daya membuat a permintaan HTTP lintas-asal ketika meminta sumber daya dari domain yang berbeda, atau port daripada yang sumber daya pertama itu sendiri layani.

enter image description here

Sebuah Halaman HTML disajikan dari http://domain-a.com membuat <img> permintaan src untuk http://domain-b.com/image.jpg.
Banyak halaman di web hari ini memuat sumber daya seperti Stylesheet CSS, gambar dan skrip dari domain terpisah (jadi seharusnya keren).

Kebijakan Asal-Sama

Untuk alasan keamanan, peramban membatasi HTTP lintas-asal permintaan dimulai dari dalam skrip.
Sebagai contoh, XMLHttpRequest dan Fetch ikuti kebijakan asal yang sama.
Jadi, aplikasi web menggunakan XMLHttpRequest atau Fetch hanya bisa membuat Permintaan HTTP untuk domain sendiri.

Pembagian Sumber Daya Lintas-Asal (CORS)

Untuk meningkatkan aplikasi web, pengembang meminta vendor browser untuk mengizinkan permintaan lintas-domain.

Itu Pembagian Sumber Daya Lintas-Asal (CORS) mekanisme memberikan server web kontrol akses lintas-domain, yang memungkinkan transfer data lintas domain yang aman.
Browser modern digunakan CORS dalam sebuah Kontainer API - seperti XMLHttpRequest atau Fetch - untuk mengurangi risiko permintaan HTTP lintas-asal.

Bagaimana CORS bekerja (Access-Control-Allow-Origin tajuk)

Wikipedia:

Standar CORS mendeskripsikan header HTTP baru yang menyediakan browser dan server cara untuk meminta URL jarak jauh hanya ketika mereka memiliki izin.

Meskipun beberapa validasi dan otorisasi dapat dilakukan oleh server, itu umumnya tanggung jawab peramban untuk mendukung tajuk-tajuk ini dan menghormati batasan yang mereka terapkan.

Contoh

  1. Browser mengirim OPTIONS meminta dengan Origin HTTP tajuk.

    Nilai tajuk ini adalah domain yang melayani halaman induk. Ketika sebuah halaman dari http://www.example.com mencoba mengakses data pengguna di service.example.com, header permintaan berikut akan dikirim ke service.example.com:

    Asal: http://www.example.com

  2. Server di service.example.com dapat menanggapi dengan:

    • Sebuah Access-Control-Allow-Origin Header (ACAO) dalam responsnya yang menunjukkan situs asal mana yang diizinkan.
      Sebagai contoh:

      Access-Control-Allow-Origin: http://www.example.com

    • Halaman kesalahan jika server tidak mengizinkan permintaan lintas-asal

    • Sebuah Access-Control-Allow-Origin Head (ACAO) dengan wildcard yang memungkinkan semua domain:

      Access-Control-Allow-Origin: *


33
2018-03-05 06:39



Jika Anda hanya ingin menguji aplikasi lintas domain di mana browser memblokir permintaan Anda, maka Anda bisa membuka browser Anda dalam mode tidak aman dan menguji aplikasi Anda tanpa mengubah kode Anda dan tanpa membuat kode Anda tidak aman. Dari MAC OS Anda dapat melakukannya dari jalur terminal:

open -a Google\ Chrome --args --disable-web-security --user-data-dir

8
2018-02-22 16:32



1. Klien mengunduh kode javascript MyCode.js dari http: // siteA - asal.

Kode yang melakukan pengunduhan - tag skrip html Anda atau xhr dari javascript atau apa pun - berasal dari, katakanlah, http: // siteZ. Dan, ketika browser meminta MyCode.js, ia mengirimkan Origin: tajuk bertuliskan "Asal: http: // siteZ", karena dapat melihat bahwa Anda meminta situsA dan siteZ! = siteA. (Anda tidak dapat menghentikan atau mengganggu ini.)

2. Header respons MyCode.js berisi Access-Control-Allow-Origin: http: // siteB, yang saya pikir berarti bahwa MyCode.js diizinkan untuk membuat referensi asal silang ke situs B.

tidak. Artinya, Hanya situsB yang diizinkan untuk melakukan permintaan ini. Jadi, permintaan Anda untuk MyCode.js dari situsZ mendapatkan kesalahan, dan peramban biasanya tidak memberi Anda apa-apa. Tetapi jika Anda membuat server Anda kembali A-C-A-O: siteZ sebagai gantinya, Anda akan mendapatkan MyCode.js. Atau jika mengirim '*', itu akan berhasil, yang akan memungkinkan semua orang masuk. Atau jika server selalu mengirim string dari Origin: header ... tapi ... untuk keamanan, jika Anda takut dengan peretas , server Anda seharusnya hanya mengizinkan asal pada daftar pendek, yang diizinkan untuk membuat permintaan tersebut.

Kemudian, MyCode.js berasal dari situsA. Ketika membuat permintaan ke situsB, semuanya adalah asal-silang, browser mengirim Origin: siteA, dan siteB harus mengambil situsA, mengenali itu pada daftar pendek dari pemohon yang diizinkan, dan mengirim kembali A-C-A-O: siteA. Hanya dengan demikian browser akan membiarkan skrip Anda mendapatkan hasil dari permintaan tersebut.


6
2018-02-27 01:37



saya bekerja dengan express 4 dan node 7.4 dan angular, saya memiliki masalah yang sama saya membantu ini:
  a) sisi server: di file app.js saya memberikan header untuk semua respons seperti:

app.use(function(req, res, next) {  
      res.header('Access-Control-Allow-Origin', req.headers.origin);
      res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
      next();
 });  

ini harus ada sebelum semua router.
Saya melihat banyak tambahan tajuk ini:

res.header("Access-Control-Allow-Headers","*");
res.header('Access-Control-Allow-Credentials', true);
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');

tetapi saya tidak membutuhkan itu,
b) sisi klien: di kirim ajax Anda perlu menambahkan: "withCredentials: true," seperti:

$http({
     method: 'POST',
     url: 'url, 
     withCredentials: true,
     data : {}
   }).then(function(response){
        // code  
   }, function (response) {
         // code 
   });

semoga berhasil.


5
2018-02-06 08:19



Menggunakan Reaksi dan Axios, gabungkan tautan proksi ke URL dan tambahkan tajuk seperti yang ditunjukkan di bawah ini

https://cors-anywhere.herokuapp.com/ + Your API URL

Hanya dengan menambahkan link Proxy akan berfungsi, tetapi juga bisa melempar kesalahan untuk No Access lagi. Maka lebih baik untuk menambahkan header seperti yang ditunjukkan di bawah ini.

axios.get(`https://cors-anywhere.herokuapp.com/[YOUR_API_URL]`,{headers: {'Access-Control-Allow-Origin': '*'}})
      .then(response => console.log(response:data);
  }

5
2017-10-16 15:53



Jika Anda menggunakan PHP, coba tambahkan kode berikut pada kemasan file php:

jika Anda menggunakan localhost, coba ini:

header("Access-Control-Allow-Origin: *");

jika Anda menggunakan domain eksternal seperti server, coba ini:

header("Access-Control-Allow-Origin: http://www.website.com");

4
2018-01-18 15:30



Untuk berbagi lintas asal, atur tajuk: 'Access-Control-Allow-Origin':'*';

Php: header('Access-Control-Allow-Origin':'*');

Node: app.use('Access-Control-Allow-Origin':'*');

Ini akan memungkinkan untuk berbagi konten untuk domain yang berbeda.


3
2017-11-28 02:39



Setiap kali saya mulai berpikir tentang CORS, intuisi saya tentang situs mana yang menghosting header tidak benar, seperti yang Anda jelaskan dalam pertanyaan Anda. Bagi saya, membantu memikirkan tujuan dari kebijakan asal yang sama.

Tujuan dari kebijakan asal yang sama adalah untuk melindungi Anda dari JavaScript berbahaya di situsA.com mengakses informasi pribadi yang Anda pilih untuk dibagikan hanya dengan situsB.com. Tanpa kebijakan asal yang sama, JavaScript yang ditulis oleh penulis situsA.com dapat membuat browser Anda membuat permintaan ke siteB.com, menggunakan cookie otentikasi Anda untuk siteB.com. Dengan cara ini, siteA.com dapat mencuri informasi rahasia yang Anda bagikan dengan siteA.com.

Terkadang Anda perlu bekerja lintas domain, yang merupakan tempat CORS. CORS melonggarkan kebijakan asal yang sama untuk domainA.com, menggunakan Access-Control-Allow-Origin tajuk ke daftar domain lain (domainB.com) yang dipercaya untuk menjalankan JavaScript yang dapat berinteraksi dengan domainA.com.

Untuk memahami domain mana yang harus melayani tajuk CORS, pertimbangkan ini. Anda mengunjungi malicious.com, yang berisi beberapa JavaScript yang mencoba membuat permintaan lintas domain ke mybank.com. Ini harus sampai ke mybank.com, bukan malicious.com, untuk memutuskan apakah atau tidak menetapkan header CORS yang mengendurkan kebijakan asal yang sama yang memungkinkan JavaScript dari malicious.com untuk berinteraksi dengannya. Jika mungkin untuk malicous.com untuk mengatur header CORS sendiri memungkinkan akses JavaScript sendiri ke mybank.com, ini akan sepenuhnya membatalkan kebijakan asal yang sama.

Saya pikir alasan untuk intuisi saya yang buruk adalah sudut pandang yang saya miliki ketika mengembangkan sebuah situs. Nya saya situs, dengan semua saya JavaScript, oleh karena itu tidak melakukan sesuatu yang berbahaya dan itu harus dilakukan saya untuk menentukan situs lain mana saya JavaScript dapat berinteraksi dengan. Padahal sebenarnya saya harus memikirkan yang mana lain situs JavaScript mencoba berinteraksi dengan situs saya dan haruskah saya menggunakan CORS untuk mengizinkannya?


3
2018-01-28 18:47