\n\nБез защиты: браузер отправляет запрос\n → Твои кукиз от twitch.tv отправляются\n → Злоумышленник получает твои данные\n →災害!\n```\n\n### Решение: Same-Origin Policy\n\n```\nSame Origin = Protocol + Domain + Port\n\nhttps://api.example.com:8000\n├── Protocol: https\n├── Domain: api.example.com\n└── Port: 8000\n\nДругие origins:\nhttps://example.com:8000 ❌ Разный домен\nhttp://api.example.com:8000 ❌ Разный протокол\nhttps://api.example.com:8001 ❌ Разный порт\n```\n\n### Как браузер блокирует запросы\n\n```python\n# Frontend на https://localhost:3000\nfetch('https://api.example.com/users')\n\n# Браузер:\n# 1. Проверяет origin источника: https://localhost:3000\n# 2. Проверяет origin целевой страницы: https://api.example.com\n# 3. Они разные → браузер блокирует запрос!\n\n# Ошибка в консоли:\n# Access to XMLHttpRequest at 'https://api.example.com/users'\n# from origin 'https://localhost:3000'\n# has been blocked by CORS policy\n```\n\n### CORS - разрешить доступ\n\n```python\n# FastAPI API\nfrom fastapi import FastAPI\nfrom fastapi.middleware.cors import CORSMiddleware\n\napp = FastAPI()\n\napp.add_middleware(\n CORSMiddleware,\n allow_origins=[\n \"https://example.com\",\n \"https://app.example.com\",\n \"http://localhost:3000\" # Разработка\n ],\n allow_credentials=True,\n allow_methods=[\"*\"], # GET, POST, PUT, DELETE и т.д.\n allow_headers=[\"*\"], # Любые заголовки\n)\n\n@app.get(\"/api/users\")\nasync def get_users():\n return [{\"id\": 1, \"name\": \"Alice\"}]\n```\n\n### Как CORS работает: Preflight запрос\n\n```\nШаг 1: Браузер отправляет OPTIONS запрос (preflight)\n\nОтправляю:\nOPTIONS /api/users HTTP/1.1\nHost: api.example.com\nOrigin: https://localhost:3000\nAccess-Control-Request-Method: POST\nAccess-Control-Request-Headers: Content-Type\n\nШаг 2: API отвечает\n\nHTTP/1.1 200 OK\nAccess-Control-Allow-Origin: https://localhost:3000\nAccess-Control-Allow-Methods: GET, POST, PUT, DELETE\nAccess-Control-Allow-Headers: Content-Type\nAccess-Control-Max-Age: 3600\n\nШаг 3: Если все ОК - браузер отправляет реальный запрос\n\nPOST /api/users HTTP/1.1\nHost: api.example.com\nOrigin: https://localhost:3000\nContent-Type: application/json\n\n{\"name\": \"Bob\"}\n```\n\n### Практический пример: Django\n\n```python\n# settings.py\nINSTALLED_APPS = [\n 'corsheaders',\n]\n\nMIDDLEWARE = [\n 'corsheaders.middleware.CorsMiddleware',\n 'django.middleware.common.CommonMiddleware',\n]\n\nCORS_ALLOWED_ORIGINS = [\n \"https://example.com\",\n \"http://localhost:3000\",\n \"http://localhost:5173\", # Vite\n]\n\nCORS_ALLOW_CREDENTIALS = True # Отправлять cookies\n```\n\n### Когда CORS блокирует\n\n```python\n# 1. Запросы с разными origin\nfetch('https://evil.com/steal-data') # ❌ Блокирован\n\n# 2. Custom headers\nfetch('/api/users', {\n headers: {\n 'X-Custom-Header': 'value' # ❌ Блокирован (нужен preflight)\n }\n})\n\n# 3. POST с Content-Type: application/json\nfetch('/api/users', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({...}) # ❌ Блокирован (нужен preflight)\n})\n\n# 4. Cookies с credentials\nfetch('/api/users', {\n credentials: 'include' # ❌ Блокирован (нужно разрешить)\n})\n```\n\n### Когда CORS НЕ блокирует (Simple Requests)\n\n```python\n# GET запрос с базовыми заголовками\nfetch('https://api.example.com/users')\n# ✅ Работает (простой запрос)\n\n# POST с application/x-www-form-urlencoded\nfetch('/api/users', {\n method: 'POST',\n body: 'name=Alice'\n})\n# ✅ Работает\n```\n\n### Правила для simple requests\n\n```\nМетод: GET, HEAD, POST\nЗаголовки:\n- Accept\n- Accept-Language\n- Content-Language\n- Content-Type: только application/x-www-form-urlencoded,\n multipart/form-data, text/plain\n```\n\n### Частые ошибки\n\n```python\n# ❌ Неправильно - слишком разрешительно\napp.add_middleware(\n CORSMiddleware,\n allow_origins=[\"*\"], # Все домены!\n allow_credentials=True, # Отправлять cookies\n)\n# Это противоречиво и небезопасно\n\n# ✅ Правильно\napp.add_middleware(\n CORSMiddleware,\n allow_origins=[\"https://example.com\"],\n allow_credentials=True,\n)\n```\n\n### Когда CORS не проблема\n\n```\nCORS блокирует браузерные запросы\n\nТак что это НЕ защита от:\n✓ Запросов с сервера на сервер\n✓ cURL запросов\n✓ Postman запросов\n✓ Mobile приложений (нет браузера)\n```\n\n### Вывод\n\nCORS - это защита браузера от XSS атак. Это не мешает разработке, а помогает:\n1. Явно указать, кто может использовать твой API\n2. Защитить пользователей от вредоносных сайтов\n3. Предотвратить утечку данных\n\nПросто правильно настрой CORS в своем API и забудь о проблемах.","dateCreated":"2026-03-22T11:29:32.321895","upvoteCount":0,"author":{"@type":"Person","name":"claude-haiku-4.5"}}}}
← Назад к вопросам

Зачем нужен CORS?

2.0 Middle🔥 181 комментариев
#REST API и HTTP#Безопасность

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Зачем нужен CORS

CORS (Cross-Origin Resource Sharing) - это механизм безопасности в браузере, который контролирует доступ к ресурсам между разными доменами. Без него браузер блокирует запросы для защиты пользователя.

Проблема: Same-Origin Policy

Есть вредоносный сайт evil.com:

<script>
  // Отправляю запрос на twitch.tv (где ты залогинен)
  fetch('https://twitch.tv/api/get-payment-info')
    .then(data => send_to_attacker(data))
</script>

Без защиты: браузер отправляет запрос
  → Твои кукиз от twitch.tv отправляются
  → Злоумышленник получает твои данные
  →災害!

Решение: Same-Origin Policy

Same Origin = Protocol + Domain + Port

https://api.example.com:8000
├── Protocol: https
├── Domain: api.example.com
└── Port: 8000

Другие origins:
https://example.com:8000        ❌ Разный домен
http://api.example.com:8000    ❌ Разный протокол
https://api.example.com:8001   ❌ Разный порт

Как браузер блокирует запросы

# Frontend на https://localhost:3000
fetch('https://api.example.com/users')

# Браузер:
# 1. Проверяет origin источника: https://localhost:3000
# 2. Проверяет origin целевой страницы: https://api.example.com
# 3. Они разные → браузер блокирует запрос!

# Ошибка в консоли:
# Access to XMLHttpRequest at 'https://api.example.com/users'
# from origin 'https://localhost:3000'
# has been blocked by CORS policy

CORS - разрешить доступ

# FastAPI API
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware

app = FastAPI()

app.add_middleware(
    CORSMiddleware,
    allow_origins=[
        "https://example.com",
        "https://app.example.com",
        "http://localhost:3000"  # Разработка
    ],
    allow_credentials=True,
    allow_methods=["*"],  # GET, POST, PUT, DELETE и т.д.
    allow_headers=["*"],  # Любые заголовки
)

@app.get("/api/users")
async def get_users():
    return [{"id": 1, "name": "Alice"}]

Как CORS работает: Preflight запрос

Шаг 1: Браузер отправляет OPTIONS запрос (preflight)

Отправляю:
OPTIONS /api/users HTTP/1.1
Host: api.example.com
Origin: https://localhost:3000
Access-Control-Request-Method: POST
Access-Control-Request-Headers: Content-Type

Шаг 2: API отвечает

HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://localhost:3000
Access-Control-Allow-Methods: GET, POST, PUT, DELETE
Access-Control-Allow-Headers: Content-Type
Access-Control-Max-Age: 3600

Шаг 3: Если все ОК - браузер отправляет реальный запрос

POST /api/users HTTP/1.1
Host: api.example.com
Origin: https://localhost:3000
Content-Type: application/json

{"name": "Bob"}

Практический пример: Django

# settings.py
INSTALLED_APPS = [
    'corsheaders',
]

MIDDLEWARE = [
    'corsheaders.middleware.CorsMiddleware',
    'django.middleware.common.CommonMiddleware',
]

CORS_ALLOWED_ORIGINS = [
    "https://example.com",
    "http://localhost:3000",
    "http://localhost:5173",  # Vite
]

CORS_ALLOW_CREDENTIALS = True  # Отправлять cookies

Когда CORS блокирует

# 1. Запросы с разными origin
fetch('https://evil.com/steal-data')  # ❌ Блокирован

# 2. Custom headers
fetch('/api/users', {
    headers: {
        'X-Custom-Header': 'value'  # ❌ Блокирован (нужен preflight)
    }
})

# 3. POST с Content-Type: application/json
fetch('/api/users', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({...})  # ❌ Блокирован (нужен preflight)
})

# 4. Cookies с credentials
fetch('/api/users', {
    credentials: 'include'  # ❌ Блокирован (нужно разрешить)
})

Когда CORS НЕ блокирует (Simple Requests)

# GET запрос с базовыми заголовками
fetch('https://api.example.com/users')
# ✅ Работает (простой запрос)

# POST с application/x-www-form-urlencoded
fetch('/api/users', {
    method: 'POST',
    body: 'name=Alice'
})
# ✅ Работает

Правила для simple requests

Метод: GET, HEAD, POST
Заголовки:
- Accept
- Accept-Language
- Content-Language
- Content-Type: только application/x-www-form-urlencoded,
                multipart/form-data, text/plain

Частые ошибки

# ❌ Неправильно - слишком разрешительно
app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],  # Все домены!
    allow_credentials=True,  # Отправлять cookies
)
# Это противоречиво и небезопасно

# ✅ Правильно
app.add_middleware(
    CORSMiddleware,
    allow_origins=["https://example.com"],
    allow_credentials=True,
)

Когда CORS не проблема

CORS блокирует браузерные запросы

Так что это НЕ защита от:
✓ Запросов с сервера на сервер
✓ cURL запросов
✓ Postman запросов
✓ Mobile приложений (нет браузера)

Вывод

CORS - это защита браузера от XSS атак. Это не мешает разработке, а помогает:

  1. Явно указать, кто может использовать твой API
  2. Защитить пользователей от вредоносных сайтов
  3. Предотвратить утечку данных

Просто правильно настрой CORS в своем API и забудь о проблемах.