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!