CORS: просто и понятно говорим про ошибки кроссдоменных запросов
Всем привет!
Меня зовут Радик, я frontend developer компании Creative. И сегодня я хочу поднять тему, которая касается и фронта и бэка, и окружает нас с вами каждый день. Речь пойдёт об ошибках CORS и как их можно обойти.
Уверен, что многим разрабам знакома ситуация, когда ты работаешь над приложением, оно запущено локально, и тебе нужно сделать из него запросы к различным удалённым ресурсам. В этот момент «что-то идёт не так», и ты видишь на своём экране миллион ошибок в консоли браузера. Почему они появляются? Давайте разбираться вместе. В этой статье расскажу о средствах защиты браузера и о том, что он может от вас скрывать в процессе кроссдоменных запросов. Фича: об ошибках будем говорить в картинках :)
SOP – Same Origin Policy
Рассмотрим кейс. Мы заходим на какой-то незнакомый сайт, созданный потенциальным злоумышленником. Внешне пока не видим ничего подозрительного, но пока мы находимся на этом сайте, злобный скрипт уже готовит запрос к серверу банка, в котором мы залогинены, и пытается получить наши данные:
Как же браузер пытается нас от этого защитить? Он использует Политику одинакового источника: Same Origin Policy (SOP).
В тех случаях, когда запрос отправляется на ресурс, у которого отличается домен / порт / протокол, – браузер по умолчанию понимает, что он кроссдоменный и применяет политику безопасности:
CORS – Cross Origin Resource Sharing
Что же делать в том случае, когда нам необходимо разрешить для браузера взаимодействие между различными ресурсами?
Браузер должен отправить в запросе заголовок:
**origin: htttps://good-website.com**
Сервер проверит, откуда к нему пришёл запрос, и (если этот домен разрешён) в ответе вернёт заголовок:
**access-control-allow-origin: htttps://good-website.com**
ACAH – Access-Control-Allow-Headers
Браузер может запретить доступ к некоторым заголовкам ответа из кода, ничего не сообщив при этом разработчику.
Так получается, потому что по умолчанию при кроссдоменных запросах браузер разрешает чтение только следующих заголовков ответа:
Cache-Control
- Content-Language
- Content-Length
- Content-Type
- Expires
- Last-Modified
- Pragma
Поэтому в network вкладке браузера мы видим абсолютно все интересующие нас заголовки, а из кода JS они будут нам недоступны.
Для того чтобы браузер разрешил доступ к этим заголовкам, в ответе должен быть указан заголовок Access-Control-Allow-Headers.
В нём нужно перечислить заголовки, доступ к которым разрешён браузером:
Специальное значение * позволяет разрешить для использования любые заголовки, но только в том случае, если в изначальном запросе нет cookie или данных аутентификации. В противном случае оно будет рассматриваться как буквальное имя заголовка «*».
Proxy как одно из возможных решений проблемы при локальной разработке
Рассмотрим ещё один кейс. Нам нужно сделать кроссдоменный запрос из приложения, которое развёрнуто локально. Но такой запрос в нужный нам момент не обрабатывается должным образом на сервере. Картинка для понимания.
Как быть? Можно запустить локальный proxy сервер, который будет пересылать данные между нашим приложением и сервером, добавляя необходимые заголовки:
Можно сделать простой proxy сервер на Node.js для решения проблемы с кроссдоменными запросами:
- Для этого переходим в директорию, в которой вы хотите создать прокси сервер
- Инициализируем Node.js проект командой npm init
- Устанавливаем необходимые пакеты командой npm install cors express http-proxy-middleware
- Создаём файл index.js со следующим содержимым:
Запускаем proxy сервер командой node index.js
- Теперь мы можем использовать адрес и порт, указанный в proxy сервере в приложении во время разработки.
На этом всё. Мы рассмотрели причины возникновения ошибки CORS и одно из возможных решений при локальной разработке на фронте. Надеюсь, мой материал будет вам полезен. Буду рад продолжить обсуждение темы в комментариях. Всем хорошего дня и поменьше ошибок CORS!
Помимо прокси сервера, для разработки можно запустить специальный инстанс браузера, в котором отключены CORS
https://alfilatov.com/posts/run-chrome-without-cors/
Спасибо за статью. Расскажите, почему в случае блокировки кроссдоменных запросов корсом, запросы из постмана могут успешно обрабатываться?
Насколько понимаю, cors - это требование браузера. И его можно отключить.
Спасибо за статью. Было очень полезно
Рисуночки класс 👍
Я нормально наелся этой ошибки когда пытался сделать на ангуляре сайтик который бы показывал мне самую выгодную позицию (руб/1г белка) в Яндекс лавке. Я вообще не по фронтенду, поэтому не знаю, какие бест практики чтобы колить внешний не зависимый API из кода фронта получается? Неужели только прокси? Или бест практика не делать так на фронте в принципе?)
Наконец понял как с этим справляться, а не полагаться на магию ответов stackoverflow