\n```\n\n**2. Proxy на бэкенде**\n\n```\nФронтенд → Свой бэкенд (/api/users) → Внешний API\nЭто обходит CORS, но добавляет latency\n```\n\n**3. WebSocket**\n\n```javascript\n// WebSocket не подвергается CORS ограничениям\nconst ws = new WebSocket('wss://api.example.com/ws');\n```\n\n### Вывод\n\nCORS — это критический механизм безопасности:\n\n- **Same-Origin Policy** — ограничивает кросс-доменные запросы\n- **CORS заголовки** — сервер разрешает конкретные источники\n- **Preflight запрос** — для сложных запросов браузер проверяет разрешение\n- **Правильная конфигурация** — критична для безопасности и функциональности\n\nЛюбой бэкенд-разработчик ДОЛЖЕН понимать и правильно конфигурировать CORS для защиты своего API.","dateCreated":"2026-03-28T21:48:08.721349","upvoteCount":0,"author":{"@type":"Person","name":"claude-haiku-4.5"}},"suggestedAnswer":[{"@type":"Answer","text":"## Использование CORS (Cross-Origin Resource Sharing)\n\nCORS (Cross-Origin Resource Sharing) — это механизм, который позволяет ограничивать и контролировать кросс-доменные запросы между браузером и сервером. CORS решает критическую проблему безопасности в веб-приложениях.\n\n### Проблема: Same-Origin Policy (SOP)\n\nВсе современные браузеры применяют **Same-Origin Policy** (SOP) — политику одного источника:\n\n```\n\"Скрипт может получать данные только с того же источника (домена, протокола и порта)\"\n\nОсновной источник: https://example.com:443\n\n✅ Разрешено:\n - https://example.com/api (тот же домен)\n - https://example.com:443/data (тот же протокол и порт)\n \n❌ Заблокировано:\n - http://example.com/api (другой протокол)\n - https://api.example.com (субдомен считается другим источником)\n - https://example2.com (другой домен)\n - https://example.com:8080 (другой порт)\n```\n\n### Пример блокировки\n\n```typescript\n// Загрузить страницу с https://myapp.com\n// Попробать запрос с фронта\nfetch('https://api.example.com/users')\n .then(r => r.json())\n .catch(e => console.log(e));\n\n// Ошибка в консоли:\n// Access to XMLHttpRequest at 'https://api.example.com/users' \n// from origin 'https://myapp.com' has been blocked by CORS policy: \n// No 'Access-Control-Allow-Origin' header is present on the requested resource.\n```\n\n### Зачем нужен CORS\n\n**1. Безопасность**\n\nCORS защищает от атак:\n\n```html\n\n\n\n\n\n```\n\n**2. Контроль доступа**\n\nСервер может разрешить доступ только конкретным клиентам:\n\n```\nСервер API (api.example.com):\n - Может разрешить запросы с app.example.com\n - Может разрешить запросы с mobile.example.com\n - Но заблокировать с hack.com\n```\n\n**3. Управление методами и заголовками**\n\nСервер может разрешить только определённые HTTP методы и заголовки.\n\n### Как работает CORS\n\n**Простой запрос (Simple Request):**\n\nДля простых запросов (GET, POST, HEAD) с стандартными заголовками:\n\n```\n1. Браузер отправляет запрос с заголовком Origin\n GET /api/users\n Host: api.example.com\n Origin: https://myapp.com\n\n2. Сервер проверяет Origin и отвечает\n HTTP/1.1 200 OK\n Access-Control-Allow-Origin: https://myapp.com\n Content-Type: application/json\n \n [{\"id\": 1, \"name\": \"John\"}]\n\n3. Браузер получает ответ и позволяет скрипту его использовать\n```\n\n**Preflight запрос (для сложных запросов):**\n\nДля сложных запросов (PUT, DELETE, PATCH) или кастомных заголовков браузер сначала отправляет **OPTIONS** запрос:\n\n```\n1. Браузер отправляет preflight (OPTIONS) запрос\n OPTIONS /api/users\n Host: api.example.com\n Origin: https://myapp.com\n Access-Control-Request-Method: PUT\n Access-Control-Request-Headers: content-type\n\n2. Сервер отвечает, что это разрешено\n HTTP/1.1 200 OK\n Access-Control-Allow-Origin: https://myapp.com\n Access-Control-Allow-Methods: GET, POST, PUT, DELETE\n Access-Control-Allow-Headers: content-type\n Access-Control-Max-Age: 86400 (кэширование на 24 часа)\n\n3. Браузер отправляет реальный запрос\n PUT /api/users/1\n ...\n \n4. Сервер отвечает нормально\n```\n\n### CORS заголовки\n\n**На стороне сервера (ответ):**\n\n```typescript\n// Express пример\nimport cors from 'cors';\n\napp.use(cors({\n origin: 'https://myapp.com', // Разрешённый источник\n methods: ['GET', 'POST', 'PUT'], // Разрешённые методы\n allowedHeaders: ['Content-Type', 'Authorization'], // Разрешённые заголовки\n credentials: true, // Разрешить cookies\n maxAge: 86400 // Кэширование preflight на 24 часа\n}));\n\n// Или вручную\napp.use((req, res, next) => {\n res.setHeader('Access-Control-Allow-Origin', 'https://myapp.com');\n res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE');\n res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization');\n res.setHeader('Access-Control-Max-Age', '86400');\n res.setHeader('Access-Control-Allow-Credentials', 'true');\n \n if (req.method === 'OPTIONS') {\n res.sendStatus(200);\n } else {\n next();\n }\n});\n```\n\n**На стороне клиента (запрос):**\n\n```typescript\n// Fetch с credentials (cookies, auth headers)\nfetch('https://api.example.com/users', {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'Authorization': 'Bearer token123'\n },\n body: JSON.stringify({ name: 'John' }),\n credentials: 'include' // Отправить cookies вместе с запросом\n})\n.then(r => r.json())\n.catch(e => console.log('CORS ошибка:', e));\n```\n\n### CORS стратегии\n\n**1. Разрешить все (небезопасно)**\n\n```typescript\napp.use(cors());\n// или\nres.setHeader('Access-Control-Allow-Origin', '*');\n```\n\n**2. Разрешить конкретные домены**\n\n```typescript\nconst allowedOrigins = [\n 'https://myapp.com',\n 'https://app.myapp.com',\n 'https://mobile.myapp.com'\n];\n\napp.use(cors({\n origin: (origin, callback) => {\n if (allowedOrigins.includes(origin) || !origin) {\n callback(null, true);\n } else {\n callback(new Error('CORS не разрешён'));\n }\n }\n}));\n```\n\n**3. Разрешить с паттернами**\n\n```typescript\napp.use(cors({\n origin: /myapp\\.com$/ // Разрешить все поддомены *.myapp.com\n}));\n```\n\n### Сценарии использования\n\n**Сценарий 1: SPA (Single Page Application)**\n\n```\nФронтенд: https://app.example.com\nБэкенд: https://api.example.com\n\nБез CORS: фронтенд не может делать запросы к бэкенду\nС CORS: бэкенд разрешает запросы с app.example.com\n```\n\n**Сценарий 2: Мобильное приложение**\n\n```\nМобильный клиент НЕ использует CORS (это только для браузера)\nМобильное приложение может напрямую подключиться к API\n\nПоэтому мобильные приложения часто используют другую авторизацию:\n- API ключи\n- OAuth токены\n- JWT токены\n```\n\n**Сценарий 3: Server-to-Server**\n\n```\nЕсли бэкенд вызывает другой бэкенд, CORS НЕ применяется\nCORS применяется только когда браузер делает запрос\n\nServer A → Server B: работает без CORS\nБраузер → Server A: CORS проверяется\n```\n\n### Проблемы и решения\n\n**Проблема: credentials не отправляются**\n\n```typescript\n// ❌ Неправильно\nfetch('https://api.example.com/users');\n\n// ✅ Правильно\nfetch('https://api.example.com/users', {\n credentials: 'include' // Отправить cookies\n});\n\n// На сервере тоже нужно разрешить\nres.setHeader('Access-Control-Allow-Credentials', 'true');\n```\n\n**Проблема: кастомные заголовки блокируются**\n\n```typescript\n// Клиент отправляет:\nfetch('https://api.example.com/users', {\n headers: {\n 'X-Custom-Header': 'value'\n }\n});\n\n// Сервер должен разрешить:\nres.setHeader('Access-Control-Allow-Headers', 'X-Custom-Header, Content-Type');\n```\n\n### Альтернативы CORS\n\n**1. JSONP (устаревший способ)**\n\n```javascript\n// Работал в старых браузерах, но не безопасный\n\n```\n\n**2. Proxy на бэкенде**\n\n```\nФронтенд → Свой бэкенд (/api/users) → Внешний API\nЭто обходит CORS, но добавляет latency\n```\n\n**3. WebSocket**\n\n```javascript\n// WebSocket не подвергается CORS ограничениям\nconst ws = new WebSocket('wss://api.example.com/ws');\n```\n\n### Вывод\n\nCORS — это критический механизм безопасности:\n\n- **Same-Origin Policy** — ограничивает кросс-доменные запросы\n- **CORS заголовки** — сервер разрешает конкретные источники\n- **Preflight запрос** — для сложных запросов браузер проверяет разрешение\n- **Правильная конфигурация** — критична для безопасности и функциональности\n\nЛюбой бэкенд-разработчик ДОЛЖЕН понимать и правильно конфигурировать CORS для защиты своего API.","dateCreated":"2026-03-28T21:48:08.721349","upvoteCount":0,"author":{"@type":"Person","name":"claude-haiku-4.5"}}]}}
← Назад к вопросам

Для чего используется CORS?

1.8 Middle🔥 191 комментариев

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

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

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

Использование CORS (Cross-Origin Resource Sharing)

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

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

Все современные браузеры применяют Same-Origin Policy (SOP) — политику одного источника:

"Скрипт может получать данные только с того же источника (домена, протокола и порта)"

Основной источник: https://example.com:443

✅ Разрешено:
  - https://example.com/api        (тот же домен)
  - https://example.com:443/data   (тот же протокол и порт)
  
❌ Заблокировано:
  - http://example.com/api         (другой протокол)
  - https://api.example.com        (субдомен считается другим источником)
  - https://example2.com           (другой домен)
  - https://example.com:8080       (другой порт)

Пример блокировки

// Загрузить страницу с https://myapp.com
// Попробать запрос с фронта
fetch('https://api.example.com/users')
  .then(r => r.json())
  .catch(e => console.log(e));

// Ошибка в консоли:
// Access to XMLHttpRequest at 'https://api.example.com/users' 
// from origin 'https://myapp.com' has been blocked by CORS policy: 
// No 'Access-Control-Allow-Origin' header is present on the requested resource.

Зачем нужен CORS

1. Безопасность

CORS защищает от атак:

<!-- Вредоносный сайт hack.com -->
<img src="https://bank.com/api/transfer?to=attacker&amount=1000">

<!-- Без CORS: браузер выполнит запрос от имени пользователя -->
<!-- С CORS: браузер заблокирует запрос, если нет правильного заголовка -->

2. Контроль доступа

Сервер может разрешить доступ только конкретным клиентам:

Сервер API (api.example.com):
  - Может разрешить запросы с app.example.com
  - Может разрешить запросы с mobile.example.com
  - Но заблокировать с hack.com

3. Управление методами и заголовками

Сервер может разрешить только определённые HTTP методы и заголовки.

Как работает CORS

Простой запрос (Simple Request):

Для простых запросов (GET, POST, HEAD) с стандартными заголовками:

1. Браузер отправляет запрос с заголовком Origin
   GET /api/users
   Host: api.example.com
   Origin: https://myapp.com

2. Сервер проверяет Origin и отвечает
   HTTP/1.1 200 OK
   Access-Control-Allow-Origin: https://myapp.com
   Content-Type: application/json
   
   [{"id": 1, "name": "John"}]

3. Браузер получает ответ и позволяет скрипту его использовать

Preflight запрос (для сложных запросов):

Для сложных запросов (PUT, DELETE, PATCH) или кастомных заголовков браузер сначала отправляет OPTIONS запрос:

1. Браузер отправляет preflight (OPTIONS) запрос
   OPTIONS /api/users
   Host: api.example.com
   Origin: https://myapp.com
   Access-Control-Request-Method: PUT
   Access-Control-Request-Headers: content-type

2. Сервер отвечает, что это разрешено
   HTTP/1.1 200 OK
   Access-Control-Allow-Origin: https://myapp.com
   Access-Control-Allow-Methods: GET, POST, PUT, DELETE
   Access-Control-Allow-Headers: content-type
   Access-Control-Max-Age: 86400  (кэширование на 24 часа)

3. Браузер отправляет реальный запрос
   PUT /api/users/1
   ...
   
4. Сервер отвечает нормально

CORS заголовки

На стороне сервера (ответ):

// Express пример
import cors from 'cors';

app.use(cors({
  origin: 'https://myapp.com',           // Разрешённый источник
  methods: ['GET', 'POST', 'PUT'],       // Разрешённые методы
  allowedHeaders: ['Content-Type', 'Authorization'],  // Разрешённые заголовки
  credentials: true,                     // Разрешить cookies
  maxAge: 86400                          // Кэширование preflight на 24 часа
}));

// Или вручную
app.use((req, res, next) => {
  res.setHeader('Access-Control-Allow-Origin', 'https://myapp.com');
  res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE');
  res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization');
  res.setHeader('Access-Control-Max-Age', '86400');
  res.setHeader('Access-Control-Allow-Credentials', 'true');
  
  if (req.method === 'OPTIONS') {
    res.sendStatus(200);
  } else {
    next();
  }
});

На стороне клиента (запрос):

// Fetch с credentials (cookies, auth headers)
fetch('https://api.example.com/users', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'Authorization': 'Bearer token123'
  },
  body: JSON.stringify({ name: 'John' }),
  credentials: 'include'  // Отправить cookies вместе с запросом
})
.then(r => r.json())
.catch(e => console.log('CORS ошибка:', e));

CORS стратегии

1. Разрешить все (небезопасно)

app.use(cors());
// или
res.setHeader('Access-Control-Allow-Origin', '*');

2. Разрешить конкретные домены

const allowedOrigins = [
  'https://myapp.com',
  'https://app.myapp.com',
  'https://mobile.myapp.com'
];

app.use(cors({
  origin: (origin, callback) => {
    if (allowedOrigins.includes(origin) || !origin) {
      callback(null, true);
    } else {
      callback(new Error('CORS не разрешён'));
    }
  }
}));

3. Разрешить с паттернами

app.use(cors({
  origin: /myapp\.com$/  // Разрешить все поддомены *.myapp.com
}));

Сценарии использования

Сценарий 1: SPA (Single Page Application)

Фронтенд: https://app.example.com
Бэкенд: https://api.example.com

Без CORS: фронтенд не может делать запросы к бэкенду
С CORS: бэкенд разрешает запросы с app.example.com

Сценарий 2: Мобильное приложение

Мобильный клиент НЕ использует CORS (это только для браузера)
Мобильное приложение может напрямую подключиться к API

Поэтому мобильные приложения часто используют другую авторизацию:
- API ключи
- OAuth токены
- JWT токены

Сценарий 3: Server-to-Server

Если бэкенд вызывает другой бэкенд, CORS НЕ применяется
CORS применяется только когда браузер делает запрос

Server A → Server B: работает без CORS
Браузер → Server A: CORS проверяется

Проблемы и решения

Проблема: credentials не отправляются

// ❌ Неправильно
fetch('https://api.example.com/users');

// ✅ Правильно
fetch('https://api.example.com/users', {
  credentials: 'include'  // Отправить cookies
});

// На сервере тоже нужно разрешить
res.setHeader('Access-Control-Allow-Credentials', 'true');

Проблема: кастомные заголовки блокируются

// Клиент отправляет:
fetch('https://api.example.com/users', {
  headers: {
    'X-Custom-Header': 'value'
  }
});

// Сервер должен разрешить:
res.setHeader('Access-Control-Allow-Headers', 'X-Custom-Header, Content-Type');

Альтернативы CORS

1. JSONP (устаревший способ)

// Работал в старых браузерах, но не безопасный
<script src="https://api.example.com/users?callback=handleData"></script>

2. Proxy на бэкенде

Фронтенд → Свой бэкенд (/api/users) → Внешний API
Это обходит CORS, но добавляет latency

3. WebSocket

// WebSocket не подвергается CORS ограничениям
const ws = new WebSocket('wss://api.example.com/ws');

Вывод

CORS — это критический механизм безопасности:

  • Same-Origin Policy — ограничивает кросс-доменные запросы
  • CORS заголовки — сервер разрешает конкретные источники
  • Preflight запрос — для сложных запросов браузер проверяет разрешение
  • Правильная конфигурация — критична для безопасности и функциональности

Любой бэкенд-разработчик ДОЛЖЕН понимать и правильно конфигурировать CORS для защиты своего API.