Wednesday

18-06-2025 Vol 19

Enabling CORS in Flask

Mengaktifkan CORS di Flask: Panduan Lengkap

Pendahuluan

Cross-Origin Resource Sharing (CORS) adalah mekanisme keamanan browser yang membatasi permintaan lintas asal untuk sumber daya web. Secara default, browser melarang skrip yang berjalan di satu asal untuk membuat permintaan ke asal yang berbeda. Hal ini mencegah potensi kerentanan keamanan, seperti skrip lintas situs (XSS).

Namun, ada saat-saat ketika Anda perlu mengizinkan permintaan lintas asal. Misalnya, jika Anda membangun API dengan Flask yang dikonsumsi oleh aplikasi frontend yang di-host di domain yang berbeda, Anda perlu mengaktifkan CORS. Tanpa CORS yang diaktifkan, browser akan memblokir permintaan dari frontend ke API Anda.

Artikel ini akan memandu Anda melalui proses mengaktifkan CORS di aplikasi Flask Anda, membahas berbagai metode dan konfigurasi untuk memenuhi berbagai kebutuhan.

Apa itu CORS?

CORS adalah mekanisme yang menggunakan header HTTP untuk memberi tahu browser apakah suatu aplikasi web yang berjalan di satu asal diizinkan untuk mengakses sumber daya dari asal yang berbeda. Browser menerapkan pembatasan ini untuk melindungi pengguna dari potensi serangan berbahaya.

Asal didefinisikan oleh protokol (http/https), domain, dan port. Dua URL dianggap memiliki asal yang sama hanya jika ketiganya cocok.

Contoh:

  • http://example.com/app1 dan http://example.com/app2 – Asal yang sama (hanya berbeda jalur)
  • http://example.com dan https://example.com – Asal berbeda (berbeda protokol)
  • http://example.com dan http://www.example.com – Asal berbeda (berbeda subdomain)
  • http://example.com:80 dan http://example.com:8080 – Asal berbeda (berbeda port)

Mengapa CORS Penting?

CORS sangat penting karena:

  1. Keamanan: Mencegah permintaan lintas situs berbahaya yang dapat membahayakan data pengguna.
  2. Fungsionalitas API: Memungkinkan aplikasi frontend untuk mengkonsumsi API yang di-host di domain yang berbeda.
  3. Pengembangan Web Modern: Mendukung arsitektur mikroservices dan decoupled frontend/backend.

Cara Mengaktifkan CORS di Flask

Ada beberapa cara untuk mengaktifkan CORS di aplikasi Flask Anda:

  1. Menggunakan Ekstensi Flask-CORS
  2. Menambahkan Header CORS Secara Manual

Kami akan membahas kedua metode secara rinci.

1. Menggunakan Ekstensi Flask-CORS

Ekstensi Flask-CORS adalah cara termudah dan direkomendasikan untuk mengaktifkan CORS di aplikasi Flask Anda. Ekstensi ini menyediakan cara yang sederhana dan fleksibel untuk mengkonfigurasi CORS untuk seluruh aplikasi Anda atau untuk rute tertentu.

Instalasi

Instal Flask-CORS menggunakan pip:

pip install Flask-CORS

Penggunaan Dasar

Untuk mengaktifkan CORS untuk seluruh aplikasi Anda, inisialisasi ekstensi Flask-CORS:

from flask import Flask
from flask_cors import CORS

app = Flask(__name__)
CORS(app)

@app.route("/")
def hello_world():
    return "<p>Hello, World!</p>"

if __name__ == '__main__':
    app.run(debug=True)

Ini akan mengaktifkan CORS untuk semua rute di aplikasi Anda, mengizinkan permintaan dari semua asal.

Konfigurasi Lanjutan

Flask-CORS menawarkan berbagai opsi konfigurasi untuk menyesuaikan perilaku CORS aplikasi Anda. Berikut adalah beberapa opsi yang paling umum:

origins

Opsi origins menentukan asal mana yang diizinkan untuk membuat permintaan lintas asal ke aplikasi Anda. Anda dapat menentukan daftar asal, string yang cocok dengan pola, atau * untuk mengizinkan semua asal (tidak direkomendasikan untuk produksi).

from flask import Flask
from flask_cors import CORS

app = Flask(__name__)
CORS(app, origins=["http://example.com", "https://www.example.org"])

@app.route("/")
def hello_world():
    return "<p>Hello, World!</p>"

if __name__ == '__main__':
    app.run(debug=True)

Contoh di atas hanya mengizinkan permintaan dari http://example.com dan https://www.example.org.

methods

Opsi methods menentukan metode HTTP mana yang diizinkan untuk permintaan lintas asal. Secara default, semua metode standar (GET, POST, PUT, DELETE, dll.) diizinkan. Anda dapat menentukan daftar metode untuk membatasi metode yang diizinkan.

from flask import Flask
from flask_cors import CORS

app = Flask(__name__)
CORS(app, methods=["GET", "POST"])

@app.route("/")
def hello_world():
    return "<p>Hello, World!</p>"

if __name__ == '__main__':
    app.run(debug=True)

Contoh di atas hanya mengizinkan permintaan GET dan POST.

allow_headers

Opsi allow_headers menentukan header mana yang diizinkan untuk digunakan dalam permintaan lintas asal. Secara default, header aman tertentu seperti Content-Type diizinkan. Anda dapat menggunakan opsi ini untuk mengizinkan header kustom atau header non-standar.

from flask import Flask
from flask_cors import CORS

app = Flask(__name__)
CORS(app, allow_headers=["Content-Type", "Authorization"])

@app.route("/")
def hello_world():
    return "<p>Hello, World!</p>"

if __name__ == '__main__':
    app.run(debug=True)

Contoh di atas mengizinkan header Content-Type dan Authorization.

expose_headers

Opsi expose_headers menentukan header mana yang dapat diakses oleh aplikasi frontend dari respons. Secara default, hanya header aman tertentu yang diizinkan untuk diakses. Anda dapat menggunakan opsi ini untuk mengekspos header kustom atau header non-standar ke frontend.

from flask import Flask
from flask_cors import CORS

app = Flask(__name__)
CORS(app, expose_headers=["X-My-Custom-Header"])

@app.route("/")
def hello_world():
    return "<p>Hello, World!</p>"

if __name__ == '__main__':
    app.run(debug=True)

Contoh di atas mengekspos header X-My-Custom-Header ke frontend.

supports_credentials

Opsi supports_credentials menentukan apakah permintaan lintas asal dapat menyertakan kredensial (cookie, header otorisasi, atau sertifikat klien). Jika diatur ke True, browser akan menyertakan kredensial dalam permintaan.

from flask import Flask
from flask_cors import CORS

app = Flask(__name__)
CORS(app, supports_credentials=True)

@app.route("/")
def hello_world():
    return "<p>Hello, World!</p>"

if __name__ == '__main__':
    app.run(debug=True)

Contoh di atas mengizinkan permintaan lintas asal untuk menyertakan kredensial. PENTING: Jika Anda mengatur ini ke `True`, Anda juga *HARUS* menentukan `origins` secara eksplisit ke daftar domain yang diizinkan. Penggunaan `origins=’*’` dengan `supports_credentials=True` akan menyebabkan kesalahan browser.

max_age

Opsi max_age menentukan berapa lama (dalam detik) hasil preflight request (OPTIONS request) dapat di-cache oleh browser. Ini dapat meningkatkan kinerja dengan menghindari permintaan preflight yang berulang.

from flask import Flask
from flask_cors import CORS

app = Flask(__name__)
CORS(app, max_age=600)  # Cache preflight results for 10 minutes

@app.route("/")
def hello_world():
    return "<p>Hello, World!</p>"

if __name__ == '__main__':
    app.run(debug=True)

Contoh di atas meng-cache hasil preflight selama 10 menit (600 detik).

Mengaktifkan CORS untuk Rute Tertentu

Anda dapat mengaktifkan CORS untuk rute tertentu dengan meneruskan rute sebagai argumen ke konstruktor CORS:

from flask import Flask
from flask_cors import CORS

app = Flask(__name__)

@app.route("/api/resource")
def api_resource():
    return "<p>API Resource</p>"

CORS(app, resources={r"/api/*": {"origins": "http://example.com"}})

if __name__ == '__main__':
    app.run(debug=True)

Dalam contoh ini, CORS hanya diaktifkan untuk rute yang cocok dengan pola /api/*, dan hanya permintaan dari http://example.com yang diizinkan.

Konfigurasi Berbasis Aplikasi

Anda juga dapat mengkonfigurasi Flask-CORS menggunakan konfigurasi aplikasi Flask:

from flask import Flask
from flask_cors import CORS

app = Flask(__name__)
app.config['CORS_HEADERS'] = 'Content-Type'
CORS(app)

@app.route("/")
def hello_world():
    return "<p>Hello, World!</p>"

if __name__ == '__main__':
    app.run(debug=True)

Ini setara dengan CORS(app, allow_headers=['Content-Type']). Konfigurasi berbasis aplikasi berguna ketika Anda ingin mengelola pengaturan CORS Anda secara terpusat, terutama dalam aplikasi yang lebih besar.

2. Menambahkan Header CORS Secara Manual

Meskipun ekstensi Flask-CORS direkomendasikan, Anda juga dapat mengaktifkan CORS dengan menambahkan header CORS secara manual ke respons Anda. Metode ini kurang fleksibel daripada menggunakan Flask-CORS, tetapi dapat berguna dalam situasi di mana Anda tidak dapat menggunakan ekstensi atau memerlukan kontrol yang lebih granular atas header CORS.

Menambahkan Header ke Respons

Untuk mengaktifkan CORS secara manual, Anda perlu menambahkan header berikut ke respons Anda:

  • Access-Control-Allow-Origin: Menentukan asal mana yang diizinkan untuk mengakses sumber daya. Anda dapat menggunakan `*` untuk mengizinkan semua asal, tetapi ini umumnya tidak direkomendasikan untuk produksi.
  • Access-Control-Allow-Methods: Menentukan metode HTTP mana yang diizinkan.
  • Access-Control-Allow-Headers: Menentukan header mana yang diizinkan dalam permintaan.
  • Access-Control-Expose-Headers: Menentukan header mana yang dapat diakses oleh aplikasi frontend dari respons.
  • Access-Control-Allow-Credentials: Menentukan apakah kredensial (cookie, header otorisasi) dapat disertakan.

Contoh

from flask import Flask, make_response

app = Flask(__name__)

@app.route("/")
def hello_world():
    response = make_response("<p>Hello, World!</p>")
    response.headers["Access-Control-Allow-Origin"] = "http://example.com"
    return response

if __name__ == '__main__':
    app.run(debug=True)

Contoh di atas menambahkan header Access-Control-Allow-Origin ke respons, mengizinkan permintaan dari http://example.com.

Menangani Preflight Request (OPTIONS)

Untuk permintaan lintas asal kompleks (permintaan yang menggunakan metode selain GET, HEAD, atau POST dengan jenis konten tertentu, atau yang menyertakan header kustom), browser akan mengirimkan preflight request menggunakan metode OPTIONS sebelum permintaan yang sebenarnya. Anda perlu menangani permintaan OPTIONS ini dan menyertakan header CORS yang sesuai dalam respons.

from flask import Flask, make_response, request

app = Flask(__name__)

@app.route("/", methods=['GET', 'OPTIONS'])
def hello_world():
    if request.method == 'OPTIONS':
        response = make_response()
        response.headers["Access-Control-Allow-Origin"] = "http://example.com"
        response.headers["Access-Control-Allow-Methods"] = "GET, POST, OPTIONS"
        response.headers["Access-Control-Allow-Headers"] = "Content-Type"
        return response
    else:
        response = make_response("<p>Hello, World!</p>")
        response.headers["Access-Control-Allow-Origin"] = "http://example.com"
        return response

if __name__ == '__main__':
    app.run(debug=True)

Contoh di atas menangani permintaan OPTIONS dan mengembalikan header CORS yang diperlukan.

Membuat Dekorator untuk Penanganan CORS

Untuk menyederhanakan proses penambahan header CORS secara manual, Anda dapat membuat dekorator:

from functools import wraps
from flask import request, make_response

def crossdomain(origin=None, methods=None, headers=None,
                max_age=21600, attach_to_all=True,
                automatic_options=True):
    if methods is not None:
        methods = ', '.join(sorted(x.upper() for x in methods))
    if headers is not None and not isinstance(headers, str):
        headers = ', '.join(x.upper() for x in headers)
    if not isinstance(origin, str):
        origin = ', '.join(origin)
    if isinstance(max_age, int):
        max_age = str(max_age)

    def get_methods():
        if methods is not None:
            return methods

        options_resp = request.environ.get('wsgi.allow_methods')
        if options_resp is None:
            return 'GET, HEAD, OPTIONS'

        return options_resp

    def decorator(f):
        def wrapped_function(*args, **kwargs):
            if automatic_options and request.method == 'OPTIONS':
                resp = make_response()
            else:
                resp = make_response(f(*args, **kwargs))
            if not attach_to_all and request.method != 'OPTIONS':
                return resp

            h = resp.headers

            h['Access-Control-Allow-Origin'] = origin
            h['Access-Control-Allow-Methods'] = get_methods()
            h['Access-Control-Max-Age'] = max_age
            if headers is not None:
                h['Access-Control-Allow-Headers'] = headers
            return resp

        f.provide_automatic_options = False
        return wraps(f)(wrapped_function)
    return decorator

Kemudian, Anda dapat menggunakan dekorator ini untuk mengaktifkan CORS untuk rute tertentu:

from flask import Flask

app = Flask(__name__)

@app.route('/')
@crossdomain(origin='*')
def hello_world():
    return '<p>Hello, World!</p>'

if __name__ == '__main__':
    app.run(debug=True)

Praktik Terbaik CORS

Berikut adalah beberapa praktik terbaik untuk mengkonfigurasi CORS:

  1. Hindari menggunakan origins='*' di produksi: Ini mengizinkan permintaan dari semua asal, yang dapat menjadi risiko keamanan. Sebagai gantinya, tentukan daftar asal yang diizinkan secara eksplisit.
  2. Konfigurasikan methods, allow_headers, dan expose_headers sesuai kebutuhan: Hanya izinkan metode, header, dan header yang terekspos yang diperlukan oleh aplikasi Anda.
  3. Gunakan supports_credentials=True dengan hati-hati: Jika Anda mengizinkan kredensial, pastikan untuk menentukan asal yang diizinkan secara eksplisit dan mengamankan aplikasi Anda dari serangan lintas situs.
  4. Gunakan ekstensi Flask-CORS: Ini menyediakan cara yang sederhana dan fleksibel untuk mengkonfigurasi CORS dan menangani sebagian besar detail untuk Anda.
  5. Uji konfigurasi CORS Anda secara menyeluruh: Pastikan bahwa CORS dikonfigurasi dengan benar dan bahwa aplikasi Anda berfungsi seperti yang diharapkan dengan permintaan lintas asal. Gunakan alat developer browser untuk memeriksa header respons dan memastikan bahwa header CORS yang sesuai hadir.
  6. Pertimbangkan implikasi keamanan: Salah konfigurasi CORS dapat menyebabkan kerentanan keamanan. Luangkan waktu untuk memahami implikasi keamanan dari setiap opsi konfigurasi dan hanya aktifkan fitur yang diperlukan oleh aplikasi Anda.

Troubleshooting Masalah CORS

Berikut adalah beberapa masalah CORS umum dan cara memecahkannya:

  1. “Permintaan lintas asal diblokir: Kebijakan Asal yang Sama melarang membaca sumber daya jarak jauh di [URL].”

    Ini berarti browser telah memblokir permintaan lintas asal karena tidak ada header CORS yang sesuai yang dikembalikan oleh server.

    Solusi: Pastikan bahwa server mengembalikan header Access-Control-Allow-Origin yang sesuai.

  2. “Preflight request gagal.”

    Ini berarti preflight request (OPTIONS request) gagal. Ini bisa disebabkan oleh berbagai alasan, seperti:

    • Server tidak menangani permintaan OPTIONS dengan benar.
    • Header CORS yang diperlukan tidak dikembalikan dalam respons OPTIONS.
    • Server mengembalikan kode status kesalahan untuk permintaan OPTIONS.

    Solusi:

    • Pastikan bahwa server menangani permintaan OPTIONS dan mengembalikan header Access-Control-Allow-Origin, Access-Control-Allow-Methods, dan Access-Control-Allow-Headers yang sesuai.
    • Periksa log server untuk setiap kesalahan yang terjadi selama preflight request.
  3. “Permintaan dengan kredensial tidak didukung jika bendera ‘Access-Control-Allow-Origin’ adalah ‘*’.”

    Ini berarti Anda mencoba menggunakan supports_credentials=True dengan origins='*'.

    Solusi: Tentukan daftar asal yang diizinkan secara eksplisit sebagai pengganti origins='*' ketika menggunakan supports_credentials=True.

  4. Header kustom tidak diizinkan.

    Ini berarti Anda mencoba menggunakan header kustom dalam permintaan lintas asal tanpa mengizinkannya secara eksplisit.

    Solusi: Tambahkan header kustom ke daftar allow_headers dalam konfigurasi CORS Anda.

Kesimpulan

Mengaktifkan CORS di aplikasi Flask Anda sangat penting untuk memungkinkan aplikasi frontend untuk mengkonsumsi API Anda yang di-host di domain yang berbeda. Ekstensi Flask-CORS adalah cara termudah dan direkomendasikan untuk mengkonfigurasi CORS, tetapi Anda juga dapat menambahkan header CORS secara manual jika diperlukan. Pastikan untuk mengikuti praktik terbaik CORS untuk mengamankan aplikasi Anda dan mencegah kerentanan keamanan potensial. Uji konfigurasi CORS Anda secara menyeluruh untuk memastikan bahwa CORS dikonfigurasi dengan benar dan bahwa aplikasi Anda berfungsi seperti yang diharapkan dengan permintaan lintas asal.

Dengan memahami prinsip dan teknik CORS yang dibahas dalam artikel ini, Anda dapat secara efektif mengelola permintaan lintas asal di aplikasi Flask Anda dan membangun aplikasi web yang aman dan fungsional.

Sumber Daya Tambahan

“`

omcoding

Leave a Reply

Your email address will not be published. Required fields are marked *