В веб-проектах в последнее время всё активнее и активнее используется размещение разного контента по разным поддоменам. Например, типична ситуация, когда статические файлы размещают на отдельных поддоменах для работы с CDN или использование поддоменов для разных языковых версий сайта, или же для разных географических локаций. Основная часть ресурсов обычно едина для всех отдельных сайтов, как правило это картинки css/js и прочая статика. Чтобы кросс-запросы между поддоменами корректно принимались браузером в плане безопасности, необходимо настроить для CORS заголовки в ответе веб-сервера.
Домены с которых разрешено загружать контент указываются на ресурсе-источнике в заголовке Access-Control-Allow-Origin
. В нём можно перечислить явно домены, с которых можно запрашивать контент, или разрешить со всех астериском ‘*’. К сожалению, разрешить поддомены по маске, например *.example.com, простым укаазанием этой маски в заголовке не удастся. Т.е. можно разрешить или всё или перечислять все домены. Что делать если этих доменов много или их неопределённый список и логичнее включить доступ по маске?
В случае использования Nginx как фронтэнда возможно решение, когда необходимый заголовок формируется в зависимости от источника запроса. То есть, будем отдавать разрешающий заголовок только если запрос приходит именно с наших поддоменов. Код для реализации этой идеи получается такой:
set $cors ""; if ($http_origin ~* (\.example\.com|\.example\.ru)) { set $cors "true"; } if ($cors = "true") { add_header 'Access-Control-Allow-Origin' "$http_origin"; add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, OPTIONS, DELETE'; add_header 'Access-Control-Allow-Credentials' 'true'; add_header 'Access-Control-Allow-Headers' 'User-Agent,Keep-Alive,Content-Type'; } proxy_pass http://backend:8080/;
Его целесообразно вынести в отдельный snippet и включать в те location
, с которых берёрется контент для остальных поддоменов. При этом мы не затрагиваем бэкэнд, что экономит производительность.