Vue Front-end Инженер

Vue Front-end Инженер

Роадмап навыков для прокачки

Зачем нужен CORS

Практики разработки ПОСетевые технологииCORS

Основная идея

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

Ключевые аспекты

  • Same-Origin Policy — базовая защита браузера, запрещающая запросы к другим доменам
  • CORS — способ «разрешить» кросс-доменные запросы через HTTP-заголовки
  • Preflight-запрос — предварительный OPTIONS-запрос для проверки разрешений
  • ЗаголовкиAccess-Control-Allow-Origin и другие управляют доступом

Плюсы CORS

  • Защита пользователей от вредоносных сайтов
  • Контролируемый доступ к API с других доменов
  • Гибкая настройка разрешений на сервере
  • Стандартизированный механизм для всех браузеров

Минусы

  • Дополнительная настройка на сервере
  • Preflight-запросы увеличивают задержку
  • Сложность отладки ошибок CORS

Частые ошибки на собеседованиях

  • Путают CORS и Same-Origin Policy (CORS — это способ обойти SOP)
  • Думают, что CORS защищает сервер (он защищает пользователя браузера)
  • Не знают про preflight-запросы для «непростых» запросов
  • Пытаются решить проблему CORS на клиенте (решается только на сервере)

Введение и проблематика

Представьте: ваш фронтенд на https://myapp.com пытается получить данные с API https://api.example.com. Браузер блокирует запрос с ошибкой CORS. Почему это происходит и зачем нужна такая защита?

CORS — это не «проблема», а механизм безопасности. Он защищает пользователей от вредоносных сайтов, которые могут украсть данные.

Какую проблему решает CORS?

CORS позволяет серверам контролировать, какие сайты могут обращаться к их ресурсам. Это баланс между:

  • Безопасностью — защита от несанкционированного доступа
  • Функциональностью — возможность легитимных кросс-доменных запросов

Базовая теория

Same-Origin Policy (SOP)

Same-Origin Policy — это фундаментальная политика безопасности браузера, которая запрещает скриптам на одной странице получать данные с другого «источника» (origin).

Origin состоит из трёх частей:

text
https://example.com:443
  │        │        │
  │        │        └── Порт
  │        └── Домен
  └── Протокол (схема)
URL AURL BОдинаковый origin?
https://example.comhttps://example.com/page✅ Да
https://example.comhttp://example.com❌ Нет (протокол)
https://example.comhttps://api.example.com❌ Нет (домен)
https://example.comhttps://example.com:8080❌ Нет (порт)

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

Без SOP вредоносный сайт мог бы:

sequenceDiagram participant User as Пользователь participant Evil as evil.com participant Bank as bank.com User->>Evil: Заходит на evil.com Evil->>Bank: fetch('/api/balance')<br/>с cookies пользователя Bank-->>Evil: Баланс: $10,000 Evil->>Evil: Крадёт данные
🚫

Если бы не SOP, любой сайт мог бы выполнять запросы к вашему банку, соцсетям, почте — используя ваши cookies!

Что такое CORS?

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

sequenceDiagram participant Browser as Браузер participant Frontend as frontend.com participant API as api.example.com Frontend->>Browser: fetch('api.example.com/data') Browser->>API: GET /data<br/>Origin: frontend.com API-->>Browser: 200 OK<br/>Access-Control-Allow-Origin: frontend.com Browser-->>Frontend: Данные получены ✅

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

Простые запросы

«Простые» запросы отправляются сразу без предварительной проверки:

Условия простого запроса:

  • Методы: GET, HEAD, POST
  • Заголовки: только «безопасные» (Accept, Content-Type и др.)
  • Content-Type: только text/plain, multipart/form-data, application/x-www-form-urlencoded
js
// Простой запрос
fetch('https://api.example.com/data')
  .then(response => response.json())
  .then(data => console.log(data));

Сервер отвечает с заголовком:

http
Access-Control-Allow-Origin: https://myapp.com

Preflight-запросы

Для «непростых» запросов браузер сначала отправляет preflight-запрос (OPTIONS):

sequenceDiagram participant Browser as Браузер participant Server as Сервер Browser->>Server: OPTIONS /api/users<br/>Origin: myapp.com<br/>Access-Control-Request-Method: DELETE Server-->>Browser: 204 No Content<br/>Access-Control-Allow-Origin: myapp.com<br/>Access-Control-Allow-Methods: DELETE Browser->>Server: DELETE /api/users/1 Server-->>Browser: 200 OK

Когда нужен preflight:

  • Методы: PUT, DELETE, PATCH
  • Кастомные заголовки: Authorization, X-Custom-Header
  • Content-Type: application/json

Практические примеры

Пример ошибки CORS

js
// frontend.com
fetch('https://api.example.com/data')
  .then(res => res.json())
  .catch(err => console.error(err));

Ошибка в консоли:

text
Access to fetch at 'https://api.example.com/data' from origin
'https://frontend.com' has been blocked by CORS policy:
No 'Access-Control-Allow-Origin' header is present.

Решение на сервере (Node.js/Express)

js
const express = require('express');
const app = express();
 
// Разрешить всем (НЕ для продакшена!)
app.use((req, res, next) => {
  res.header('Access-Control-Allow-Origin', '*');
  next();
});

Основные CORS-заголовки

ЗаголовокОписаниеПример
Access-Control-Allow-OriginРазрешённый originhttps://myapp.com или *
Access-Control-Allow-MethodsРазрешённые методыGET, POST, PUT
Access-Control-Allow-HeadersРазрешённые заголовкиContent-Type, Authorization
Access-Control-Allow-CredentialsРазрешить cookiestrue
Access-Control-Max-AgeКэш preflight (секунды)86400
⚠️

Нельзя использовать Access-Control-Allow-Origin: * вместе с credentials: true. Нужно указать конкретный origin.


Пограничные кейсы

Cookies и credentials

Для отправки cookies в кросс-доменных запросах нужно:

На клиенте:

js
fetch('https://api.example.com/data', {
  credentials: 'include' // Отправлять cookies
});

На сервере:

http
Access-Control-Allow-Origin: https://myapp.com
Access-Control-Allow-Credentials: true

Несколько разрешённых origins

js
const allowedOrigins = ['https://app1.com', 'https://app2.com'];
 
app.use((req, res, next) => {
  const origin = req.headers.origin;
  if (allowedOrigins.includes(origin)) {
    res.header('Access-Control-Allow-Origin', origin);
  }
  next();
});

Плюсы и минусы

АспектОписание
БезопасностьЗащита от CSRF-подобных атак через JavaScript
КонтрольСервер решает, кому разрешить доступ
СтандартРаботает одинаково во всех браузерах
НастройкаТребует конфигурации на сервере
PreflightДополнительные запросы увеличивают latency
ОтладкаОшибки CORS не всегда информативны

Вопросы интервьюера

Q: Что такое CORS и зачем он нужен?

CORS — механизм, позволяющий серверам контролировать доступ к ресурсам с других доменов. Нужен для безопасного обхода Same-Origin Policy.

Q: CORS защищает сервер или клиент?

CORS защищает пользователя браузера от вредоносных сайтов. Сервер может обрабатывать запросы от любого источника — CORS работает только в браузере.

Q: Можно ли обойти CORS?

На клиенте — нельзя (это безопасность браузера). Можно использовать прокси-сервер, который добавит нужные заголовки.

Q: Что такое preflight-запрос?

Это предварительный OPTIONS-запрос, который браузер отправляет перед «непростыми» запросами для проверки разрешений.


Источники