Buka rahasia CORS (Cross-Origin Resource Sharing) dan pelajari cara mengaktifkan permintaan lintas-domain dengan aman di aplikasi web Anda. Panduan komprehensif ini mencakup semuanya dari dasar hingga konfigurasi tingkat lanjut, memastikan komunikasi yang lancar dan aman antar origin yang berbeda.
Mengungkap Misteri CORS: Panduan Komprehensif untuk Cross-Origin Resource Sharing
Di web yang saling terhubung saat ini, aplikasi sering kali perlu mengakses sumber daya dari origin yang berbeda. Di sinilah Cross-Origin Resource Sharing (CORS) berperan. CORS adalah mekanisme keamanan penting yang mengatur bagaimana peramban web menangani permintaan dari satu origin (domain, protokol, dan port) ke origin yang berbeda. Memahami CORS sangat penting bagi setiap pengembang web untuk membangun aplikasi web yang aman dan fungsional.
Apa itu Kebijakan Same-Origin?
Sebelum mendalami CORS, penting untuk memahami Kebijakan Same-Origin (SOP). SOP adalah mekanisme keamanan fundamental yang diterapkan di peramban web. Tujuannya adalah untuk mencegah skrip berbahaya di satu situs web mengakses data sensitif di situs web lain. Sebuah origin didefinisikan oleh kombinasi protokol (misalnya, HTTP atau HTTPS), domain (misalnya, example.com), dan nomor port (misalnya, 80 atau 443). Dua URL dianggap memiliki origin yang sama jika keduanya berbagi protokol, domain, dan port yang sama.
Contoh:
http://example.com/app1
danhttp://example.com/app2
- Origin Sama (protokol, domain, dan port sama)https://example.com/app1
danhttp://example.com/app1
- Origin Berbeda (protokol berbeda)http://example.com:8080/app1
danhttp://example.com/app1
- Origin Berbeda (port berbeda)http://sub.example.com/app1
danhttp://example.com/app1
- Origin Berbeda (subdomain berbeda – dianggap domain berbeda)
SOP membatasi skrip untuk mengakses sumber daya dari origin yang berbeda kecuali ada tindakan spesifik, seperti CORS, yang diterapkan untuk mengizinkannya.
Mengapa CORS Diperlukan?
Meskipun Kebijakan Same-Origin sangat penting untuk keamanan, kebijakan ini juga bisa bersifat membatasi. Banyak aplikasi web modern mengandalkan pengambilan data dari server yang berbeda, seperti API atau jaringan pengiriman konten (CDN). CORS menyediakan cara terkontrol untuk melonggarkan SOP dan mengizinkan permintaan lintas-origin yang sah sambil tetap menjaga keamanan.
Pertimbangkan skenario di mana aplikasi web yang di-hosting di http://example.com
perlu mengambil data dari server API yang di-hosting di http://api.example.net
. Tanpa CORS, peramban akan memblokir permintaan ini karena SOP. CORS memungkinkan server API untuk secara eksplisit menentukan origin mana yang diizinkan untuk mengakses sumber dayanya, sehingga memungkinkan aplikasi web berfungsi dengan benar.
Cara Kerja CORS: Dasar-dasarnya
CORS bekerja melalui serangkaian header HTTP yang dipertukarkan antara klien (peramban) dan server. Server menggunakan header ini untuk memberi tahu peramban apakah diizinkan untuk mengakses sumber daya yang diminta. Header HTTP kunci yang terlibat adalah Access-Control-Allow-Origin
.
Skenario 1: Permintaan Sederhana
"Permintaan sederhana" adalah permintaan GET, HEAD, atau POST yang memenuhi kriteria spesifik (misalnya, header Content-Type
adalah salah satu dari application/x-www-form-urlencoded
, multipart/form-data
, atau text/plain
). Dalam kasus ini, peramban mengirimkan permintaan langsung ke server, dan server merespons dengan header Access-Control-Allow-Origin
.
Permintaan Klien (dari http://example.com):
GET /data HTTP/1.1
Host: api.example.net
Origin: http://example.com
Respons Server (dari http://api.example.net):
HTTP/1.1 200 OK
Access-Control-Allow-Origin: http://example.com
Content-Type: application/json
{
"data": "Beberapa data dari server"
}
Dalam contoh ini, server merespons dengan Access-Control-Allow-Origin: http://example.com
, yang menunjukkan bahwa permintaan dari http://example.com
diizinkan. Jika origin dalam permintaan tidak cocok dengan nilai di header Access-Control-Allow-Origin
(atau jika header tidak ada), peramban akan memblokir respons dan mencegah skrip sisi klien mengakses data.
Skenario 2: Permintaan Preflight (untuk Permintaan Kompleks)
Untuk permintaan yang lebih kompleks, seperti yang menggunakan metode HTTP seperti PUT, DELETE, atau yang memiliki header kustom, peramban melakukan permintaan "preflight" menggunakan metode HTTP OPTIONS. Permintaan preflight ini meminta izin kepada server sebelum mengirimkan permintaan yang sebenarnya. Server merespons dengan header yang menentukan metode, header, dan origin mana yang diizinkan.
Permintaan Preflight Klien (dari http://example.com):
OPTIONS /data HTTP/1.1
Host: api.example.net
Origin: http://example.com
Access-Control-Request-Method: PUT
Access-Control-Request-Headers: X-Custom-Header
Respons Server (dari http://api.example.net):
HTTP/1.1 200 OK
Access-Control-Allow-Origin: http://example.com
Access-Control-Allow-Methods: GET, PUT, DELETE
Access-Control-Allow-Headers: X-Custom-Header, Content-Type
Access-Control-Max-Age: 3600
Penjelasan Header:
Access-Control-Allow-Origin: http://example.com
- Menunjukkan bahwa permintaan darihttp://example.com
diizinkan.Access-Control-Allow-Methods: GET, PUT, DELETE
- Menentukan metode HTTP yang diizinkan untuk permintaan lintas-origin.Access-Control-Allow-Headers: X-Custom-Header, Content-Type
- Mencantumkan header kustom yang diizinkan dalam permintaan sebenarnya.Access-Control-Max-Age: 3600
- Menentukan durasi (dalam detik) di mana respons preflight dapat di-cache oleh peramban. Ini membantu mengurangi jumlah permintaan preflight.
Jika respons preflight dari server menunjukkan bahwa permintaan diizinkan, peramban akan melanjutkan dengan permintaan yang sebenarnya. Jika tidak, peramban akan memblokir permintaan tersebut.
Permintaan Aktual Klien (dari http://example.com):
PUT /data HTTP/1.1
Host: api.example.net
Origin: http://example.com
X-Custom-Header: some-value
Content-Type: application/json
{
"data": "Beberapa data yang akan diperbarui"
}
Respons Server (dari http://api.example.net):
HTTP/1.1 200 OK
Access-Control-Allow-Origin: http://example.com
Content-Type: application/json
{
"status": "Data berhasil diperbarui"
}
Header CORS Umum
Berikut adalah rincian header CORS utama yang perlu Anda pahami:
Access-Control-Allow-Origin
: Header ini adalah yang paling fundamental. Ini menentukan origin mana yang diizinkan untuk mengakses sumber daya. Nilai yang mungkin termasuk:- Origin spesifik (misalnya,
http://example.com
). *
(wildcard): Ini mengizinkan permintaan dari origin manapun. Gunakan dengan hati-hati, karena dapat membahayakan keamanan jika data sensitif terlibat. Sebaiknya dihindari di lingkungan produksi.
- Origin spesifik (misalnya,
Access-Control-Allow-Methods
: Header ini menentukan metode HTTP (misalnya, GET, POST, PUT, DELETE) yang diizinkan untuk permintaan lintas-origin. Ini digunakan dalam respons preflight.Access-Control-Allow-Headers
: Header ini mencantumkan header kustom yang diizinkan dalam permintaan lintas-origin. Ini juga digunakan dalam respons preflight.Access-Control-Allow-Credentials
: Header ini menunjukkan apakah server mengizinkan kredensial (misalnya, cookie, header otorisasi) untuk disertakan dalam permintaan lintas-origin. Ini harus diatur ketrue
jika Anda perlu mengirim kredensial. Di sisi klien, Anda juga perlu mengaturwithCredentials = true
pada objek XMLHttpRequest.Access-Control-Expose-Headers
: Secara default, peramban hanya mengekspos serangkaian header respons yang terbatas (misalnya,Cache-Control
,Content-Language
,Content-Type
,Expires
,Last-Modified
,Pragma
) ke skrip sisi klien. Jika Anda ingin mengekspos header lain, Anda perlu mencantumkannya di headerAccess-Control-Expose-Headers
.Access-Control-Max-Age
: Header ini menentukan jumlah waktu maksimum (dalam detik) di mana peramban dapat menyimpan cache permintaan preflight. Nilai yang lebih lama mengurangi jumlah permintaan preflight, meningkatkan kinerja.
CORS dalam Berbagai Bahasa Sisi Server
Menerapkan CORS biasanya melibatkan konfigurasi aplikasi sisi server Anda untuk mengirim header CORS yang sesuai. Berikut adalah contoh cara melakukannya dalam berbagai bahasa dan kerangka kerja:
Node.js dengan Express
Anda dapat menggunakan paket middleware cors
:
const express = require('express');
const cors = require('cors');
const app = express();
// Aktifkan CORS untuk semua origin (GUNAKAN DENGAN HATI-HATI DI LINGKUNGAN PRODUKSI)
app.use(cors());
// Atau, konfigurasikan CORS untuk origin tertentu
// app.use(cors({
// origin: 'http://example.com'
// }));
app.get('/data', (req, res) => {
res.json({ message: 'Ini diaktifkan CORS untuk semua origin!' });
});
app.listen(3000, () => {
console.log('Server berjalan di port 3000');
});
Python dengan Flask
Anda dapat menggunakan ekstensi Flask-CORS
:
from flask import Flask
from flask_cors import CORS
app = Flask(__name__)
CORS(app)
# Atau, konfigurasikan CORS untuk origin tertentu
# CORS(app, resources={r"/api/*": {"origins": "http://example.com"}})
@app.route("/data")
def hello():
return {"message": "Ini diaktifkan CORS untuk semua origin!"}
if __name__ == '__main__':
app.run(debug=True)
Java dengan Spring Boot
Anda dapat mengonfigurasi CORS di aplikasi Spring Boot Anda menggunakan anotasi atau kelas konfigurasi:
Menggunakan Anotasi:
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@CrossOrigin(origins = "http://example.com") // Izinkan permintaan dari http://example.com
public class DataController {
@GetMapping("/data")
public String getData() {
return "Ini diaktifkan CORS untuk http://example.com!";
}
}
Menggunakan Konfigurasi:
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/data")
.allowedOrigins("http://example.com") // Izinkan permintaan dari http://example.com
.allowedMethods("GET", "POST", "PUT", "DELETE")
.allowedHeaders("*");
}
}
PHP
"Ini diaktifkan CORS untuk http://example.com!");
echo json_encode($data);
?>
CORS dan Pertimbangan Keamanan
Meskipun CORS memungkinkan permintaan lintas-origin, sangat penting untuk mengimplementasikannya dengan aman. Berikut adalah beberapa pertimbangan penting:
- Hindari menggunakan
*
untukAccess-Control-Allow-Origin
di lingkungan produksi: Ini mengizinkan permintaan dari origin manapun, yang bisa menjadi risiko keamanan. Sebaliknya, tentukan secara eksplisit origin yang diizinkan untuk mengakses sumber daya Anda. - Validasi header
Origin
di sisi server: Meskipun Anda menggunakan kerangka kerja yang menangani konfigurasi CORS, merupakan praktik yang baik untuk memvalidasi headerOrigin
di sisi server untuk memastikan bahwa permintaan berasal dari origin yang diharapkan. - Hati-hati dengan
Access-Control-Allow-Credentials
: Jika Anda menggunakan kredensial (misalnya, cookie, header otorisasi), pastikan untuk mengaturAccess-Control-Allow-Credentials: true
di sisi server danwithCredentials = true
di sisi klien. Namun, perlu diketahui bahwa penggunaanAccess-Control-Allow-Origin: *
tidak diizinkan ketikaAccess-Control-Allow-Credentials
diatur ketrue
. Anda harus secara eksplisit menentukan origin yang diizinkan. - Konfigurasikan
Access-Control-Allow-Methods
danAccess-Control-Allow-Headers
dengan benar: Hanya izinkan metode dan header HTTP yang diperlukan agar aplikasi Anda berfungsi dengan benar. Ini membantu mengurangi permukaan serangan. - Gunakan HTTPS: Selalu gunakan HTTPS untuk aplikasi web dan API Anda untuk melindungi data saat transit.
Pemecahan Masalah CORS
Masalah CORS bisa membuat frustrasi saat di-debug. Berikut adalah beberapa masalah umum dan cara menyelesaikannya:
- "No 'Access-Control-Allow-Origin' header is present on the requested resource": Ini adalah kesalahan CORS yang paling umum. Ini berarti server tidak mengirimkan header
Access-Control-Allow-Origin
dalam responsnya. Periksa kembali konfigurasi sisi server Anda untuk memastikan bahwa header dikirim dengan benar. - "Response to preflight request doesn't pass access control check: It does not have HTTP ok status": Kesalahan ini menunjukkan bahwa permintaan preflight gagal. Ini bisa terjadi jika server tidak dikonfigurasi untuk menangani permintaan OPTIONS atau jika header
Access-Control-Allow-Methods
atauAccess-Control-Allow-Headers
tidak dikonfigurasi dengan benar. - "The value of the 'Access-Control-Allow-Origin' header in the response is not equal to the origin in the request": Kesalahan ini berarti bahwa origin dalam permintaan tidak cocok dengan nilai di header
Access-Control-Allow-Origin
. Pastikan server mengirimkan origin yang benar dalam respons. - Cache peramban: Terkadang, peramban dapat menyimpan cache respons CORS, yang dapat menyebabkan perilaku tak terduga. Coba bersihkan cache peramban Anda atau gunakan peramban lain untuk melihat apakah itu menyelesaikan masalah. Anda juga dapat menggunakan header
Access-Control-Max-Age
untuk mengontrol berapa lama peramban menyimpan cache respons preflight.
Alat Debugging:
- Alat Pengembang Peramban: Gunakan alat pengembang peramban (biasanya diakses dengan menekan F12) untuk memeriksa permintaan dan respons jaringan. Cari header dan pesan kesalahan terkait CORS.
- Pemeriksa CORS Online: Ada alat online yang dapat membantu Anda menguji konfigurasi CORS Anda. Alat-alat ini mengirimkan permintaan ke server Anda dan menganalisis header respons untuk mengidentifikasi potensi masalah.
Skenario CORS Tingkat Lanjut
Meskipun konsep dasar CORS relatif mudah dipahami, ada beberapa skenario yang lebih canggih untuk dipertimbangkan:
- CORS dengan subdomain: Jika Anda perlu mengizinkan permintaan dari beberapa subdomain (misalnya,
app1.example.com
,app2.example.com
), Anda tidak bisa begitu saja menggunakan wildcard seperti*.example.com
di headerAccess-Control-Allow-Origin
. Sebaliknya, Anda perlu secara dinamis menghasilkan headerAccess-Control-Allow-Origin
berdasarkan headerOrigin
dalam permintaan. Ingatlah untuk memvalidasi origin terhadap daftar putih subdomain yang diizinkan untuk mencegah kerentanan keamanan. - CORS dengan banyak origin: Jika Anda perlu mengizinkan permintaan dari beberapa origin spesifik, Anda tidak dapat menentukan banyak origin di header
Access-Control-Allow-Origin
(misalnya,Access-Control-Allow-Origin: http://example.com, http://another.com
tidak valid). Sebaliknya, Anda perlu secara dinamis menghasilkan headerAccess-Control-Allow-Origin
berdasarkan headerOrigin
dalam permintaan. - CORS dan CDN: Saat menggunakan CDN untuk melayani API Anda, Anda perlu mengonfigurasi CDN untuk meneruskan header
Origin
ke server asal Anda dan untuk menyimpan cache headerAccess-Control-Allow-Origin
dengan benar. Konsultasikan dokumentasi penyedia CDN Anda untuk instruksi spesifik.
Praktik Terbaik CORS
Untuk memastikan implementasi CORS yang aman dan efisien, ikuti praktik terbaik berikut:
- Prinsip Hak Istimewa Terendah: Hanya izinkan set minimum origin, metode, dan header yang diperlukan agar aplikasi Anda berfungsi dengan benar.
- Tinjau Konfigurasi CORS Secara Berkala: Seiring perkembangan aplikasi Anda, tinjau konfigurasi CORS Anda secara berkala untuk memastikan konfigurasinya masih sesuai dan aman.
- Gunakan Kerangka Kerja atau Pustaka: Manfaatkan kerangka kerja atau pustaka yang ada yang menyediakan dukungan CORS bawaan. Ini dapat menyederhanakan implementasi dan mengurangi risiko kesalahan.
- Pantau Pelanggaran CORS: Terapkan pemantauan untuk mendeteksi dan menanggapi potensi pelanggaran CORS.
- Tetap Terkini: Ikuti terus spesifikasi CORS terbaru dan rekomendasi keamanan.
Kesimpulan
CORS adalah mekanisme keamanan penting yang memungkinkan permintaan lintas-origin terkontrol dalam aplikasi web. Memahami cara kerja CORS dan cara mengonfigurasinya dengan benar sangat penting bagi setiap pengembang web. Dengan mengikuti pedoman dan praktik terbaik yang diuraikan dalam panduan komprehensif ini, Anda dapat membangun aplikasi web yang aman dan fungsional yang berinteraksi secara mulus dengan sumber daya dari origin yang berbeda.
Ingatlah untuk selalu memprioritaskan keamanan dan hindari penggunaan konfigurasi CORS yang terlalu permisif. Dengan mempertimbangkan secara cermat implikasi keamanan dari pengaturan CORS Anda, Anda dapat melindungi aplikasi dan data Anda dari akses yang tidak sah.
Kami harap panduan ini telah membantu Anda mengungkap misteri CORS. Selamat membuat kode!