Ответ
CORS (Cross-Origin Resource Sharing) — это механизм безопасности, реализованный в браузерах, который контролирует запросы с одного домена (origin) к ресурсам другого домена. Сервер должен явно разрешить такие кросс-доменные запросы.
Последовательность проверки:
-
Определение "простого" (simple) запроса: Браузер сразу отправляет основной запрос (без предварительной проверки), если он удовлетворяет всем критериям:
- Методы: GET, POST, HEAD.
- Заголовки: Только стандартные (
Accept,Accept-Language,Content-Language,Content-Typeс значениямиapplication/x-www-form-urlencoded,multipart/form-data,text/plain).
-
Предварительный запрос (Preflight Request) для "непростых" запросов: Если запрос не является "простым" (например, использует кастомный заголовок
X-API-Keyили методPUT), браузер автоматически отправляет предварительный запрос методомOPTIONSна тот же URL.OPTIONS /api/data HTTP/1.1 Origin: https://myfrontend.com Access-Control-Request-Method: PUT Access-Control-Request-Headers: X-API-Key, Content-Type -
Ответ сервера на Preflight: Сервер должен ответить с заголовками, разрешающими запрос:
HTTP/1.1 204 No Content Access-Control-Allow-Origin: https://myfrontend.com Access-Control-Allow-Methods: GET, POST, PUT Access-Control-Allow-Headers: X-API-Key, Content-Type Access-Control-Max-Age: 86400 // Кэшировать ответ на 24 часа -
Основной запрос: Только если предварительный ответ удовлетворителен, браузер отправляет основной запрос. В ответе на основной запрос также должен присутствовать заголовок
Access-Control-Allow-Origin.
Настройка в ASP.NET Core:
// В Program.cs
app.UseCors(builder => builder
.WithOrigins("https://trusted-domain.com") // Конкретный origin
.AllowAnyMethod() // Или .AllowMethods("GET", "POST")
.AllowAnyHeader() // Или .WithHeaders("X-API-Key")
.AllowCredentials()); // Разрешить куки/авторизацию
// Важно: при использовании AllowCredentials() нельзя использовать WithOrigins("*").
Важно: CORS — это защита браузера. Инструменты вроде Postman или curl отправляют запросы напрямую и не выполняют проверки CORS.
Ответ 18+ 🔞
А, CORS, блядь! Ну это ж классика, ёпта! Сидишь такой, пишешь фронтенд, всё работает, а потом — бац! — в консоли браузера красным: «CORS policy blocked». И ты такой: «Какого хуя? У меня же API отвечает!»
Вот смотри, это такая защита в браузерах, чтобы один сайт не мог тайком с другого сайта данные стянуть. Представь, зашёл ты на «левый-сайт.ру», а он в фоне запросил твою переписку из ВК. Пиздец, да? Вот чтобы такого не было, браузер и спрашивает у сервера: «Мужик, можно этому сайту к тебе обращаться?»
Как эта хуйня работает, по шагам:
-
Простые запросы. Если ты шлёшь обычный GET или POST с простыми заголовками — браузер сразу отправляет запрос, без лишних телодвижений. Как будто стучишь в дверь и сразу заходишь.
-
А вот если ты выёбываешься — ставишь кастомный заголовок
X-API-Keyили методPUTиспользуешь — браузер тебе сразу: «Стоять, блядь!». И шлёт предварительный запрос (preflight) методомOPTIONS. Это как спросить: «Чувак, можно я к тебе зайду и вот так вот сделаю?». Выглядит это так:OPTIONS /api/data HTTP/1.1 Origin: https://мой-фронтенд.com Access-Control-Request-Method: PUT Access-Control-Request-Headers: X-API-Key, Content-Type -
Сервер должен ответить по-братски. Мол, да, вали, я тебя знаю.
HTTP/1.1 204 No Content Access-Control-Allow-Origin: https://мой-фронтенд.com Access-Control-Allow-Methods: GET, POST, PUT Access-Control-Allow-Headers: X-API-Key, Content-Type Access-Control-Max-Age: 86400 // Чтоб не спамить OPTIONS, кэш на сутки -
И только тогда, получив добро, браузер отправит твой настоящий, основной запрос. И в ответе на него тоже должен быть заголовок
Access-Control-Allow-Origin. А то опять ругань будет.
Как это в ASP.NET Core настроить, чтобы не бомбило:
// В Program.cs
app.UseCors(builder => builder
.WithOrigins("https://мой-доверенный-сайт.com") // Чётко указываешь, кто может
.AllowAnyMethod() // Или точечно: .AllowMethods("GET", "POST")
.AllowAnyHeader() // Или .WithHeaders("X-API-Key")
.AllowCredentials()); // Если с куками/авторизацией работаешь
// Важный момент, запомни как «Отче наш»: если AllowCredentials() используешь, WithOrigins("*") уже нельзя. Нахуй такую щедрость, безопасность важнее.
И главное, что всех новичков вводит в ступор: CORS — это защита браузера, ёпта! Postman, curl, да любой другой инструмент — им похуй на эти заголовки, они шлют запросы куда хотят. А браузер — тот ещё контролёр, блядь. Так что если в Постмане всё летает, а в браузере нет — ищи проблему именно в этих заголовках, а не в логике API.