Как работает механизм CORS в веб-приложениях?

Ответ

CORS (Cross-Origin Resource Sharing) — это механизм безопасности браузера, который позволяет веб-странице запрашивать ресурсы с другого домена, отличного от того, с которого была загружена сама страница. По умолчанию, браузеры блокируют такие запросы из-за политики Same-Origin Policy, если сервер явно не разрешил их.

Принцип работы:

  1. Простые запросы (GET, HEAD, POST с Content-Type: application/x-www-form-urlencoded, multipart/form-data, text/plain): Браузер отправляет запрос напрямую, добавляя заголовок Origin. Сервер должен ответить с заголовком Access-Control-Allow-Origin.
  2. Сложные запросы (PUT, DELETE, запросы с кастомными заголовками или другими Content-Type): Браузер сначала отправляет предварительный запрос (preflight request) методом OPTIONS.
    • Этот OPTIONS запрос содержит заголовки Access-Control-Request-Method и Access-Control-Request-Headers, указывающие, какой метод и заголовки будут использоваться в реальном запросе.
    • Сервер должен ответить на OPTIONS запрос с соответствующими CORS-заголовками (Access-Control-Allow-Origin, Access-Control-Allow-Methods, Access-Control-Allow-Headers, Access-Control-Max-Age).
    • Если preflight запрос успешен, браузер отправляет основной запрос.

Ключевые заголовки ответа сервера:

  • Access-Control-Allow-Origin: Указывает, каким доменам разрешен доступ (например, * для всех или https://example.com).
  • Access-Control-Allow-Methods: Перечисляет разрешенные HTTP-методы (например, GET, POST, PUT, DELETE).
  • Access-Control-Allow-Headers: Перечисляет разрешенные HTTP-заголовки.
  • Access-Control-Max-Age: Время (в секундах), в течение которого результаты preflight запроса могут быть кэшированы.

Пример настройки CORS в Flask с flask-cors:

from flask import Flask
from flask_cors import CORS

app = Flask(__name__)
# Разрешить CORS для всех маршрутов /api/* только с домена https://example.com
CORS(app, resources={r"/api/*": {"origins": "https://example.com"}})

@app.route("/api/data")
def get_data():
    return {"message": "Hello from API"}

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

Важно: CORS — это механизм безопасности, реализуемый браузером. Сервер должен самостоятельно проверять Origin заголовок и проводить дополнительную авторизацию/аутентификацию, так как злоумышленник может подделать Origin при прямом запросе, минуя браузер.