Ketahui perbedaan antara permintaan HTTP Sederhana dan XHR.
Aplikasi Web Asal - https://github.com
Saat Anda membuka situs web dengan mengetik Aplikasi Web Asal, browser Anda membuat permintaan HTTP Sederhana. CORS tidak berlaku di sini. Karena kami secara sukarela meminta untuk menyajikan konten dari Origin Web App. Browser Anda akan/harus menyajikannya tanpa masalah apa pun. Namun, jika menyangkut permintaan XHR, JavaScript yang dimuat oleh Origin Web App di browser Anda dapat membuat permintaan ke server mana pun (https://netflix.com) yang meminta sumber daya. Sekarang, Aplikasi Web Asal dimiliki oleh Github tetapi https://netflix.com dimiliki oleh Netflix, server tersebut berpotensi melayani apa saja. Github tidak dapat mengendalikan server milik Netflix. Hal ini memiliki banyak implikasi keamanan yang berpotensi mencuri konten dari satu situs web (bisa berupa situs web keuangan) ke server jarak jauh mana pun.
Untungnya, CORS mengatasi masalah ini dengan sangat baik dengan serangkaian aturan tertentu.
Ini adalah standar yang ditentukan oleh W3C untuk mengaktifkan permintaan lintas asal antara klien (browser) dan server untuk berbagi sumber daya sekaligus menjaga keamanan. Browser apa pun akan mematuhi standar ini untuk mencegah memuat sumber daya dari server pihak ketiga mana pun.
Header menunjukkan dari mana permintaan berasal. Itu dikirim dengan permintaan CORS, serta dengan permintaan POST.
Sintaksis:
Origin: <scheme> "://" <hostname> [":" <port> ]
Contoh:
Origin: https://netflix.com
Origin: http://netflix.com:443
Origin: http://localhost:1443
Header ini digunakan oleh browser saat mengeluarkan permintaan pra-penerbangan untuk menunjukkan metode permintaan mana yang akan digunakan saat permintaan sebenarnya dibuat.
Sintaksis:
Access-Control-Request-Method: <method>
<method>
dapat berupa GET
, POST
atau DELETE
.
Contoh:
Access-Control-Request-Method: POST
Header ini sekali lagi digunakan dalam permintaan pra-penerbangan oleh browser untuk menunjukkan header permintaan mana yang akan digunakan ketika permintaan sebenarnya dibuat. Untuk menggunakan beberapa header, harus dipisahkan dengan koma.
Sintaksis:
Access-Control-Request-Headers: <header-name>
Access-Control-Request-Headers: <header-name>, <header-name>
Contoh:
Access-Control-Request-Headers: X-PINGOTHER, Content-Type
Penting: Semua header harus masuk dalam daftar aman CORS atau header khusus seperti X-Custom-Header
.
Accept
Accept-Language
Content-Language
Content-Type
Nilai yang diperbolehkan adalah application/x-www-form-urlencoded
, multipart/form-data
dan text/plain
.
Header berikut dikembalikan dalam permintaan pra-penerbangan.
Header ini menunjukkan jika Asal yang diminta diizinkan. Browser Anda akan memilih untuk berhasil/gagal permintaan dengan mencocokkan asal yang diminta dengan ini.
Sintaksis:
Access-Control-Allow-Origin: *
Untuk permintaan tanpa kredensial, nilai *
dapat ditentukan sebagai wildcard. Ini memberitahu browser Anda untuk mengizinkan permintaan dari Asal mana pun.
Access-Control-Allow-Origin: <origin>
Ketika Anda hanya menerima satu Asal di header respons, itu berarti server/aplikasi web Anda berdasarkan Origin
yang diminta, ia merespons dengan Origin
yang sama jika diizinkan. Server Anda juga harus merespons dengan Bervariasi untuk menunjukkan bahwa bervariasi berdasarkan header permintaan.
Contoh:
Access-Control-Allow-Origin: https://github.com
Browser Anda akan membuat permintaan sebenarnya jika salah satu nilai di header ini cocok. Ketika wildcard *
dikembalikan, berarti metode apa pun diperbolehkan.
Sintaksis:
Access-Control-Allow-Methods: <method>, <method>, ...
Access-Control-Allow-Methods: *
Contoh:
Access-Control-Allow-Methods: GET, POST
Browser Anda akan membuat permintaan sebenarnya jika semua header yang diminta diizinkan.
Sintaksis:
Access-Control-Allow-Headers: <header-name>, <header-name>
Access-Control-Allow-Headers: *
Contoh:
Access-Control-Allow-Headers: Accept, Content-Type
Wildcard *
memberi tahu browser bahwa header apa pun diperbolehkan.
Memberi tahu berapa lama hasil pra-penerbangan dapat di-cache.
Access-Control-Max-Age: <delta-seconds>
maksimal tidak. detik hasilnya dapat di-cache.
Setiap browser memiliki batas maksimal,
Vary header secara umum digunakan untuk tujuan caching untuk menentukan apakah respons yang di-cache dapat digunakan atau harus di-cache ulang berdasarkan nilai header.
Di CORS, katakanlah server mengizinkan banyak asal berdasarkan Origin
yang diminta, server tersebut akan mengembalikan URL tertentu di Access-Control-Allow-Origin
.
Sintaksis:
Vary: <header-name>
Contoh:
Katakanlah github.com mengizinkan https://github.com dan https://netflix.com untuk meminta sumber daya. Pertimbangkan skenario berikut,
Skenario 1:
curl -X OPSI https://github.com/api/v1/gists/1
Origin: https://github.com
Access-Control-Request-Method: GET
Access-Control-Request-Headers: Content-Type
Access-Control-Allow-Origin: https://github.com
Vary: Origin
Access-Control-Allow-Methods: GET, POST
Access-Control-Allow-Headers: Content-Type
Access-Control-Max-Age: 600
Sekarang dalam skenario ini, browser akan menyimpan hasil permintaan pra-penerbangan ini selama 10 menit.
Skenario 2:
curl -X OPSI https://github.com/api/v1/gists/1
Origin: https://netflix.com
Access-Control-Request-Method: GET
Access-Control-Request-Headers: Content-Type
Access-Control-Allow-Origin: https://netflix.com
Vary: Origin
Access-Control-Allow-Methods: GET, POST
Access-Control-Allow-Headers: Content-Type
Access-Control-Max-Age: 300
Sekarang Anda dapat memperhatikan bahwa Access-Control-Allow-Origin
berisi https://netflix.com, ini adalah contoh bagaimana respons bervariasi berdasarkan Origin
yang diberikan. Begitu juga dengan usia maksimal respons ini yang di-cache hanya 5 menit tidak seperti skenario pertama.
Beberapa permintaan tidak memicu permintaan pra-penerbangan untuk CORS. Ini kami menyebutnya sebagai permintaan sederhana . Itu harus memenuhi ketentuan berikut:
Salah satu metode yang diperbolehkan:
Selain header yang secara otomatis dibuat oleh agen pengguna (misalnya, Connection
atau User-Agent
), satu-satunya header yang diperbolehkan untuk disetel secara manual adalah header permintaan yang masuk dalam daftar aman CORS dan yang berikut ini:
DPR
Downlink
Save-Data
Viewport-Width
Width
Tidak ada pemroses peristiwa yang terdaftar pada objek XMLHttpRequestUpload
apa pun yang digunakan dalam permintaan.
Tidak ada objek ReadableStream
yang digunakan dalam permintaan.
Contoh:
Meminta:
GET /api/v1/public-data/ HTTP/1.1
Host: bar.com
User-Agent: curl/7.69.1
Accept: */*
Origin: https://foo.com
Header Respons:
HTTP/1.1 200 OK
Access-Control-Allow-Origin: *
Connection: Keep-Alive
Transfer-Encoding: chunked
Content-Type: application/xml
Ketika permintaan mengembalikan *
di header Access-Control-Allow-Origin
. Artinya permintaan dapat dibuat dari Host
mana pun. Dalam hal ini, browser Anda tidak akan membuat permintaan pra-penerbangan.
Browser Anda akan membuat permintaan pra-penerbangan untuk menentukan apakah permintaan sebenarnya aman untuk dikirim.
Contoh:
const xhr = new XMLHttpRequest ( ) ;
xhr . open ( 'POST' , 'https://bar.com/api/v1/post-here/' ) ;
xhr . setRequestHeader ( 'X-PINGOTHER' , 'pingpong' ) ;
xhr . setRequestHeader ( 'Content-Type' , 'application/json;charset=UTF-8' ) ;
xhr . onreadystatechange = handler ;
xhr . send ( JSON . stringify ( { "email" : "[email protected]" } ) ) ;
Permintaan Pra-penerbangan:
OPTIONS /api/v1/post-here/
Host: bar.com
User-Agent: curl/7.69.1
Accept: */*
Origin: https://foo.com
Access-Control-Request-Method: POST
Access-Control-Request-Headers: X-PINGOTHER, Content-Type
HTTP/1.1 200 OK
Connection: Keep-Alive
Content-Type: application/json
Access-Control-Allow-Origin: https://foo.com
Access-Control-Allow-Methods: GET, POST
Access-Control-Allow-Headers: X-PINGOTHER, Content-Type, Accept
Permintaan Sebenarnya:
POST -d '{foo: bar}' /api/v1/post-here/
Host: bar.com
User-Agent: curl/7.69.1
Accept: */*
Origin: https://foo.com
X-PINGOTHER: pingpong
Content-Type: application/json;charset=UTF-8
HTTP/1.1 200 OK
Connection: Keep-Alive
Content-Type: application/json
Access-Control-Allow-Origin: https://foo.com
Jika header non-standar seperti X-PINGOTHER
disetel, browser Anda tidak akan mengetahui apakah aman untuk membuat permintaan. Untuk memastikan keamanannya, browser Anda membuat permintaan OPTIONS dengan Access-Control-Request-Headers
yang berisi X-PINGOTHER
dan Content-Type
. Setelah memvalidasi dengan header respons permintaan pra-penerbangan, browser Anda membuat permintaan sebenarnya.
Secara umum, saat Anda membuat permintaan XHR, cookie tidak diteruskan bersamaan dengan permintaan. Jika ada kebutuhan untuk meneruskan cookie, Anda harus menyetel tanda pada objek XMLHttpRequest
.
const xhr = new XMLHttpRequest ( ) ;
const url = 'http://bar.com/api/v1/credentialed-content/' ;
function callOtherDomain ( ) {
if ( invocation ) {
xhr . open ( 'GET' , url , true ) ;
xhr . withCredentials = true ;
xhr . onreadystatechange = handler ;
xhr . send ( ) ;
}
}
Meminta:
POST -d '{foo: bar}' /api/v1/post-here/
Host: bar.com
User-Agent: curl/7.69.1
Accept: */*
Origin: https://foo.com
X-PINGOTHER: pingpong
Content-Type: application/json;charset=UTF-8
Cookie: _session=NyV14oKXiS6HHopaf9nT
Ketika permintaan dibuat XMLHttpRequest
dan flag withCredentials
disetel, browser Anda akan meneruskan Cookie
di header permintaan.
Tanggapan:
HTTP/1.1 200 OK
Connection: Keep-Alive
Content-Type: application/json
Access-Control-Allow-Origin: https://foo.com
Access-Control-Allow-Credentials: true
Cache-Control: no-cache
Pragma: no-cache
Set-Cookie: _session=AjBSqxj4T7bSySNTWeEm; expires=Wed, 31-05-2020 00:00:00 GMT
Saat browser Anda melihat Access-Control-Allow-Credentials
disetel ke true. Ini akan menghormati header Set-Cookie
dan menyetel cookie.
Penting: Wildcard "*" tidak boleh disetel di Access-Control-Allow-Origin
seperti yang disebutkan di bagian Permintaan dan wildcard yang diberi kredensial.
Ketika permintaan kredensial dibuat dengan menyetel bendera withCredentials
, Access-Control-Expose-Headers
harus disetel oleh server agar browser mengetahui header mana yang dapat diakses.
Di dunia pra-kors, secara default header respons tidak dapat diakses oleh browser dalam permintaan CORS. Jadi dibuat eksplisit agar browser akan mencari header ini untuk membaca header yang terekspos. Dengan cara ini spesifikasi CORS memastikan browser lama tidak rusak.
Ini dikembalikan dalam permintaan pra-penerbangan. Ketika browser Anda melihat ini, ia dapat mengakses header Set-Cookie
. Seperti yang kami sebutkan di atas, dalam permintaan XHR normal, browser Anda tidak akan meneruskan Cookie
di header permintaan serta membaca header respons Set-Cookie
.
Sintaksis:
Access-Control-Allow-Credentials: true
Anda dapat menemukan contoh di bagian Permintaan dengan kredensial.
Saat kami mengatakan permintaan yang diberi kredensial, itu berarti cookie diteruskan dalam permintaan XHR atau disetel melalui header respons Set-Cookie
. Ketika permintaan XHR dibuat dengan tanda withCredentials, Anda berharap menerima respons bersama dengan cookie yang akan disetel. Namun, Anda tidak dapat mengharapkan Access-Control-Allow-Origin
menjadi "*" karena itu berarti situs web mana pun dapat menggunakan cookie ini. Karena alasan ini, browser Anda akan menggagalkan permintaan jika melihat "*" di header respons Access-Control-Allow-Origin
.
Jika permintaan pra-penerbangan merespons dengan 301/302, beberapa browser mungkin tidak mendukungnya saat ini. Anda mungkin mendapatkan kesalahan seperti,
The request was redirected to 'https://example.com/foo', which is disallowed for cross-origin requests that require preflight
Request requires preflight, which is disallowed to follow cross-origin redirect
Catatan: Untuk solusinya, periksa Permintaan preflighted dan dokumen pengalihan oleh Mozilla.
Browser memiliki pengaturan untuk menolak semua cookie third-party
, ketika pengguna mengaktifkannya. Misalnya, jika permintaan dibuat dari https://foo.com
dan server berada di https://bar.com
, browser Anda tidak akan menyetel cookie yang dikirim oleh https://bar.com
.