CORS - Bagaimana melakukan 'preflight' sebuah httprequest?

94

Saya mencoba membuat permintaan HTTP lintas domain ke layanan WCF (yang saya miliki). Saya telah membaca beberapa teknik untuk mengatasi batasan skrip lintas domain. Karena layanan saya harus mengakomodasi permintaan GET dan POST, saya tidak dapat menerapkan beberapa tag skrip dinamis yang srcnya adalah URL permintaan GET. Karena saya bebas membuat perubahan di server, saya mulai mencoba menerapkan solusi yang melibatkan konfigurasi respons server untuk menyertakan header "Access-Control-Allow-Origin" dan permintaan 'preflight' dengan dan OPTIONS request. Saya mendapat ide dari posting ini: Membuat CORS berfungsi

Di sisi server, metode web saya menambahkan 'Access-Control-Allow-Origin: *' ke respons HTTP. Saya dapat melihat bahwa tanggapan menyertakan tajuk ini sekarang. Pertanyaan saya adalah: Bagaimana cara 'melakukan preflight' permintaan (OPTIONS)? Saya menggunakan jQuery.getJSON untuk membuat permintaan GET tetapi browser langsung membatalkan permintaan dengan yang terkenal:

Asal http: // localhost tidak diizinkan oleh Access-Control-Allow-Origin

Apakah ada yang akrab dengan teknik CORS ini? Perubahan apa yang perlu dilakukan pada klien untuk melakukan pra-penerbangan atas permintaan saya?

Terima kasih!

Nick
sumber

Jawaban:

158

Selama permintaan preflight, Anda akan melihat dua header berikut: Access-Control-Request-Method dan Access-Control-Request-Headers. Header permintaan ini meminta izin dari server untuk membuat permintaan sebenarnya. Respons preflight Anda perlu mengakui tajuk ini agar permintaan yang sebenarnya dapat berfungsi.

Misalnya, browser membuat permintaan dengan header berikut:

Origin: http://yourdomain.com
Access-Control-Request-Method: POST
Access-Control-Request-Headers: X-Custom-Header

Server Anda kemudian harus merespons dengan header berikut:

Access-Control-Allow-Origin: http://yourdomain.com
Access-Control-Allow-Methods: GET, POST
Access-Control-Allow-Headers: X-Custom-Header

Berikan perhatian khusus pada header respons Access-Control-Allow-Headers. Nilai header ini harus sama dengan header di header permintaan Access-Control-Request-Headers, dan tidak boleh '*'.

Setelah Anda mengirimkan respons ini ke permintaan preflight, browser akan membuat permintaan sebenarnya. Anda dapat mempelajari lebih lanjut tentang CORS di sini: http://www.html5rocks.com/en/tutorials/cors/

monsur
sumber
dapatkah Anda menambahkan beberapa domain ke Access-Control-Allow-Origin?
botbot
@botbot Anda mungkin sudah mengerjakan ini sekarang tetapi jika orang lain bertanya-tanya dapat melakukannyaAccess-Control-Allow-Origin: *
Steve Chambers
2
Saya mungkin melewatkan sesuatu. Jadi, haruskah saya mengirim dua permintaan XMLHttp? Satu untuk preflight; periksa respon sukses dan kemudian kirim pertanyaan sebenarnya?
Kangkan
14
@Kangkan kamu tidak perlu khawatir untuk mengirimkan permintaan preight. Jika permintaan membutuhkan preflight, browser akan mengirimkannya untuk Anda.
monsur
4
TERIMA KASIH untuk sedikit 'membayar perhatian khusus' ... yang memecahkan masalah saya dengan node / expressjs Saya dapat menambahkan filter untuk menangkap permintaan preflight ini//cors and preflight filtering app.all('*', function(req, res, next){.. //preflight needs to return exact request-header res.set('Access-Control-Allow-Headers', req.headers['access-control-request-headers']); if ('OPTIONS' == req.method) return res.send(204);next(); });
Kurtfm
0

Meskipun utas ini berasal dari tahun 2014, masalahnya masih terkini bagi banyak dari kita. Berikut adalah cara saya mengatasinya dalam konteks jQuery 1.12 / PHP 5.6:

  • jQuery mengirim permintaan XHR-nya hanya dengan menggunakan header terbatas; hanya 'Origin' yang dikirim.
  • Tidak diperlukan permintaan preflight.
  • Server hanya perlu mendeteksi permintaan seperti itu, dan menambahkan "Access-Control-Allow-Origin:". $ _SERVER ['HTTP_ORIGIN'], setelah mendeteksi bahwa ini adalah XHR lintas sumber.

Contoh Kode PHP:

if (!empty($_SERVER['HTTP_ORIGIN'])) {
    // Uh oh, this XHR comes from outer space...
    // Use this opportunity to filter out referers that shouldn't be allowed to see this request
    if (!preg_match('@\.partner\.domain\.net$@'))
        die("End of the road if you're not my business partner.");

    // otherwise oblige
    header("Access-Control-Allow-Origin: " . $_SERVER['HTTP_ORIGIN']);
}
else {
    // local request, no need to send a specific header for CORS
}

Secara khusus, jangan tambahkan exit;karena tidak diperlukan penerbangan awal.

Fabien Haddadi
sumber