Русские Блоги
Аннотируйте @CrossOrigin для решения междоменных проблем
Аннотация @CrossOrigin
По соображениям безопасности браузеры запрещают Ajax-вызовы ресурсов, находящихся за пределами текущего источника. Например, когда вы проверяете свой банковский счет на одной вкладке, у вас может быть веб-сайт EVILL на другой вкладке. Скрипт от EVILL не может делать Ajax-запросы к API вашего банка (снимать деньги с вашего счета!) С вашими учетными данными.
1. Междоменная поддержка (CORS):
Spring Framework 4.2 GA предоставляет CORS первый тип поддержки, что делает его более простым и мощным по настройке, чем обычные решения на основе фильтров. Таким образом, версия springMVC должна быть 4.2 или выше для поддержки @CrossOrigin.
2. Как пользоваться:
1. Контроллер настраивает CORS
1.1. CORS-конфигурация метода контроллера, вы можете добавить аннотацию @CrossOrigin к методу обработчика аннотации @RequestMapping, чтобы включить CORS (по умолчанию @CrossOrigin разрешает все источники и методы HTTP, указанные в аннотации @RequestMapping):
2 параметра в @CrossOrigin:
origins : Список доступных доменов
maxAge: Максимальное время (в секундах), в течение которого кеш длится до подготовки ответа.
1.2, включите @CrossOrigin для всего контроллера
В этом примере междоменная поддержка включена для методов обработки retrieve () и remove (). Вы также можете увидеть, как настроить конфигурацию CORS с помощью атрибута @CrossOrigin.
1.3 Используя конфигурацию CORS на уровне контроллера и метода, Spring объединит два атрибута аннотации для создания объединенной конфигурации CORS.
1.4 Если вы используете Spring Security, убедитесь, что CORS включен на уровне безопасности Spring и разрешите ему использовать преимущества конфигурации, определенной на уровне Spring MVC.
2. Глобальная конфигурация CORS
В дополнение к мелкозернистой конфигурации на основе аннотаций вам может также потребоваться определить некоторые глобальные конфигурации CORS. Это похоже на использование фильтров, но может быть объявлено как Spring MVC и в сочетании с мелкозернистой конфигурацией @CrossOrigin. По умолчанию разрешены все источники и методы GET, HEAD и POST.
Упростите CORS всего приложения, чтобы:
Если вы используете Spring Boot, рекомендуется объявить bean-компонент WebMvcConfigurer следующим образом:
Вы можете легко изменить любой атрибут и применить эту конфигурацию CORS только к определенным шаблонам пути:
Если вы используете Spring Security, обязательно включите CORS на уровне безопасности Spring и позвольте ему использовать конфигурацию, определенную на уровне Spring MVC.
3. Пространство имен XML
Вы также можете настроить пространство имен CORS и MVC XML.
a. Если доступны все методы всего проекта, вы можете настроить его следующим образом; эта минимальная конфигурация XML позволяет CORS иметь те же атрибуты по умолчанию, что и JavaConfig в режиме пути / **:
Где * означает соответствие следующему слою;** означает, что независимо от количества слоев, они могут быть сопоставлены.
Можно сопоставить следующие пути:
Не может соответствовать:
Поскольку * может соответствовать только пути следующего слоя, если вы хотите сопоставить, независимо от того, сколько слоев позади, конфигурация выглядит следующим образом:
Примечание. Фактически, один (*) становится двумя (**)
б. Вы также можете объявить несколько сопоставлений CORS с настраиваемыми атрибутами:
c. Если вы используете Spring Security, не забудьтеВключить CORS на уровне безопасности Spring:
4、How does it work?
Запросы CORS (включая предварительно выбранные методы с параметрами) автоматически отправляются в различные зарегистрированные HandlerMapping. Они обрабатывают запросы на подготовку CORS и перехватывают простые и актуальные запросы CORS благодаря реализации CorsProcessor (по умолчанию по умолчаниюDefaultCorsProcessorProcessor), чтобы добавить соответствующие заголовки ответов CORS (например, Access-Control-Allow-Origin). ЧтобыCorsConfigurationПозволяет указать, как должен обрабатываться запрос CORS: разрешить источники, заголовки, методы и т. Д.
a、AbstractHandlerMapping#setCorsConfiguration() Позволяет указать отображение, которых существует несколькоCorsConfigurationСопоставление с шаблоном пути, например / api / **.
б) Подклассы могут предоставлять свои собственные CorsConfiguration, переопределяя метод getCorsConfiguration (Object, HttpServletRequest) класса AbstractHandlerMapping.
c. Процедура обработки может быть реализована CorsConfigurationSource Интерфейс (например, ResourceHttpRequestHandler ) Чтобы обеспечитьCorsConfiguration。
5. Поддержка CORS на основе фильтров.
В-третьих, причина, по которой весенняя аннотация @CrossOrigin не работает
1. Для поддержки @CrossOrigin версия springMVC должна быть 4.2 или выше.
2. Non- @ CrossOrigin не решил проблему междоменных запросов, но неправильные запросы приводили к невозможности получения ожидаемого ответа, что заставляло браузер выдавать междоменные проблемы.
3. После добавления аннотации @CrossOrigin над аннотацией контроллера междоменные проблемы все еще возникают. Одно из решений:
Методы Get и Post не указаны в аннотации @RequestMapping, после указанного, проблема решается.
Аналогичный код выглядит следующим образом:
CORS для чайников: история возникновения, как устроен и оптимальные методы работы
В этой статье подробно разобрана история и эволюция политики одинакового источника и CORS, а также расписаны разные типы доступа между различными источниками, а также несколько оптимальных решений работы с ними.
Если вы давно хотели разобраться в CORS и вас достали постоянные ошибки, добро пожаловать под кат.
Ошибка в консоли вашего браузера
No ‘Access-Control-Allow-Origin’ header is present on the requested resource.
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at https://example.com/
Access to fetch at ‘https://example.com’ from origin ‘http://localhost:3000’ has been blocked by CORS policy.
Я уверен, вам уже доводилось видеть похожие сообщения об ошибках в консоли вашего браузера. Если нет, не волнуйтесь, скоро увидите. Все программисты достаточно часто натыкаются на CORS-ошибки.
Эти всплывающие ошибки в процессе разработки просто раздражают. Но на самом деле, CORS — это невероятно полезный механизм в мире неправильно настроенных веб серверов, злоумышленников, орудующих в интернете и организаций, продвигающих веб-стандарты.
Но давайте-ка пойдем к истокам…
В начале был первый субресурс
Верни мне мой 1993 г.
Источники & cross-origin
Источник идентифицируется следующей тройкой параметров: схема, полностью определенное имя хоста и порт. Например, и имеют разные источники: первый использует схему http, а второй https. Вдобавок, портом для http по умолчанию является 80, тогда как для https — 443. Следовательно, в данном примере 2 источника отличаются схемой и портом, тогда как хост один и тот же (example.com).
Таким образом, если хотя бы один из трех элементов у двух ресурсов отличается, то источник ресурсов также считается разным.
Если, к примеру, мы будем сравнивать источник с другими источниками, то мы получим следующие результаты:
| URL | Результат | Причина |
| Тот же | Отличается только путь | |
| Тот же | Отличается только путь | |
| Отличен | Разные протоколы | |
| Отличен | Отличается порт (https:// порт является по умолчанию 443) | |
| Отличен | Разный хост |
Пример запроса между различными источниками: когда ресурс (то есть, страница) типа попробует отобразить тег из источника (заметьте, что схема поменялась!).
Слишком много опасностей запроса между различными источниками
Теперь, когда мы определились, что такое совместное использования ресурсов между разными и одинаковыми источниками, давайте посмотрим, в чем же дело.
Когда тег появился во Всемирной Паутине, мы тем самым открыли ящик Пандоры. Некоторое время спустя в Сети появились теги
Русские Блоги
@CrossOrigin подробное объяснение
Каталог статей
Аннотация @CrossOrigin
По соображениям безопасности браузеры запрещают Ajax-вызовы ресурсов, находящихся за пределами текущего источника. Например, когда вы проверяете свой банковский счет на одной вкладке, у вас может быть веб-сайт EVILL на другой вкладке. Скрипт от EVILL не может делать Ajax-запросы к вашему банковскому API (снимать деньги с вашего счета!) С вашими учетными данными.
1. Междоменная поддержка (CORS):
Spring Framework 4.2 GA обеспечивает первоклассную поддержку CORS, что упрощает и упрощает его настройку по сравнению с обычными решениями на основе фильтров. Таким образом, версия springMVC должна быть 4.2 или выше для поддержки @CrossOrigin.
2. Как пользоваться:
1. Контроллер настраивает CORS
1.1 CORS конфигурация метода контроллера
Вы можете добавить аннотацию @CrossOrigin к методу обработчика аннотации @RequestMapping, чтобы включить CORS (по умолчанию @CrossOrigin разрешает все источники и HTTP-методы, указанные в аннотации @RequestMapping):
2 параметра в @CrossOrigin:
1.2, включите @CrossOrigin для всего контроллера
В этом примере междоменная поддержка включена для методов обработки retrieve () и remove (). Вы также можете увидеть, как настроить конфигурацию CORS с помощью атрибута @CrossOrigin.
1.3, используйте конфигурацию CORS на уровне контроллера и метода
Spring объединит два атрибута аннотации для создания объединенной конфигурации CORS.
1.4, если вы используете Spring Security
Обязательно включите CORS на уровне безопасности Spring и позвольте ему использовать преимущества конфигурации, определенной на уровне Spring MVC.
2. Глобальная конфигурация CORS
В дополнение к мелкозернистой конфигурации на основе аннотаций вам может также потребоваться определить некоторые глобальные конфигурации CORS. Это похоже на использование фильтров, но может быть объявлено как Spring MVC и в сочетании с мелкозернистой конфигурацией @CrossOrigin. По умолчанию разрешены все источники и методы GET, HEAD и POST.
3. Пространство имен XML
Вы также можете настроить пространство имен CORS и MVC XML.
а. Если доступны все методы всего проекта, вы можете настроить его так
Эта минимальная конфигурация XML заставляет CORS иметь те же атрибуты по умолчанию, что и JavaConfig в режиме пути / **:
Среди них * означает соответствие следующему слою; ** означает, что независимо от того, сколько слоев существует, он может быть сопоставлен.
Можно сопоставить следующие пути:
Поскольку * может соответствовать только пути следующего слоя, если вы хотите сопоставить, независимо от того, сколько слоев существует, конфигурация будет следующей:
Примечание. Фактически, один (*) становится двумя (**)
б. Вы также можете объявить несколько сопоставлений CORS с настраиваемыми атрибутами:
c. Если вы используете Spring Security, не забудьте включить CORS на уровне безопасности Spring:
4、How does it work?
a、 AbstractHandlerMapping#setCorsConfiguration() Позволяет указать отображение, которых существует несколько CorsConfiguration Сопоставьте шаблон пути, например / api / **.
б. Подклассы можно переписывать AbstractHandlerMapping категория getCorsConfiguration(Object, HttpServletRequest) Способ предоставить свой собственный CorsConfiguration 。
c. Программа обработки может быть реализована CorsConfigurationSource Интерфейс (например, ResourceHttpRequestHandler ) Предоставлять по одному на каждый запрос CorsConfiguration 。
5. Поддержка CORS на основе фильтров.
В качестве альтернативы другим методам, упомянутым выше, среда Spring также предоставляет CorsFilter. В этом случае вам не нужно использовать @CrossOrigin или WebMvcConfigurer # addCorsMappings (CorsRegistry). Например, вы можете объявить следующий фильтр в приложении Spring Boot:
В-третьих, причина, по которой весенняя аннотация @CrossOrigin не работает
Методы Get и Post не указаны в аннотации @RequestMapping. После определенного указанного проблема решается.
Аналогичный код выглядит следующим образом:
Активация CORS для RESTful Web-сервиса
Этот урок освещает создание «hello world» RESTful web сервиса с использованием Spring, который включает заголовки для Cross-Origin Resource Sharing (CORS) в ответе.
Что вы создадите
Вы создадите сервис, который будет принимать HTTP GET запросы на:
а ответом будет JSON строка вида:
Вы можете модифицировать сообщение ответа, если добавить к строке запроса параметр name :
Значение параметра name заменяет значение по умолчанию «World» отображается в ответе:
Этот сервис немного отличается от описанного в Создание RESTful Web-сервиса тем, что он имеет фильтр, который добавляет CORS заголовки к ответу.
Что вам потребуется
Как проходить этот урок
Как и большинство уроков по Spring, вы можете начать с нуля и выполнять каждый шаг, либо пропустить базовые шаги, которые вам уже знакомы. В любом случае, вы в конечном итоге получите рабочий код.
Чтобы начать с нуля, перейдите в Настройка проекта.
Настройка проекта
Для начала вам необходимо настроить базовый скрипт сборки. Вы можете использовать любую систему сборки, которая вам нравится для сборки проетов Spring, но в этом уроке рассмотрим код для работы с Gradle и Maven. Если вы не знакомы ни с одним из них, ознакомьтесь с соответсвующими уроками Сборка Java-проекта с использованием Gradle или Сборка Java-проекта с использованием Maven.
Создание структуры каталогов
Создание файла сборки Gradle
Ниже представлен начальный файл сборки Gradle. Файл pom.xml находится здесь. Если вы используете Spring Tool Suite (STS), то можете импортировать урок прямо из него.
Spring Boot gradle plugin предоставляет множество удобных возможностей:
Создание класса, представляющего ресурс
Теперь, когда вы настроили проект и систему сборки, вы можете создать ваш web-сервис.
Для начала подумаем о взаимодействии с сервисом.
Для модели представления приветствия вам необходимо создать класс, представляющего ресурс. Он представляет собой простой java-объект с полями, конструкторами и методами доступа к значениям id и content :
Далее вы создаете контроллер ресурса, который будет обрабатывать эти приветствия.
Создание контроллера ресурса
Этот контроллер краток и прост, однако внутри происходит много чего. Давайте разберем его шаг за шагом.
Аннотация @RequestMapping гарантирует, что HTTP-запросы на /greeting будут сопоставлены greeting() методу.
Ключевое отличие можду традиционным MVC контроллером и контроллером RESTful web-сервиса выше в создании тела HTTP-ответа. Вместо того, чтобы опираться на view-технологию для рендеринга на серверной стороне сообщения приветствия в HTML, RESTful web-сервис контроллер просто заполняет и возвращает Greeting объект. Данные объекта будут записаны напрямую в HTTP-ответ как JSON.
Аннотация @ResponseBody в методе greeting() говорит Spring MVC, что не нужно отображать объект приветствия через слой представления на стороне сервера, а вместо этого писать его напрямую в телоответа.
Greeting объект должен быть конвертирован в JSON. Благодаря поддержке Spring HTTP конвертера, вам не требуется выполнять эту конвертацию вручную. Когда Jackson 2 в classpath, MappingJackson2HttpMessageConverter из Spring выбирается автоматически для конвертации экземпляра Greeting в JSON.
Фильтр запросов CORS
Т.к. RESTful web сервис будет включать CORS заголовки контроля доступа в свой ответ, вам необходимо написать фильтр, который добавляет заголовки к ответу. Ниже приведенный класс SimpleCORSFilter обеспечивает простой реализацией для такого фильтра:
Как уже было написано, SimpleCORSFilter отвечает на все запросы с определенными Access-Control-* заголовками. В данном случае, заголовки установлены на разрешение POST, GET, OPTIONS или DELETE запросов от клиентов любого хоста. Результат предполетного запроса может быть кеширован до 3600 секунд(1 час) и запрос может содержать x-requested-with заголовок.
Создание приложения исполняемым
Несмотря на то, что возможно упаковать этот сервис в традиционный WAR файл для разертывания на стороннем сервере приложений, более простой подход, продемонстрированный ниже создает отдельное самостоятельное приложение. Вы упаковываете все в единый, исполняемый JAR-файл, который запускается через хорошо знакомый старый main() Java-метод. Попутно, вы используете поддержку Spring для встроенного Tomcat контейнера сервлетов как HTTP среду выполнения вместо развертывания на сторонний экземпляр.
Сборка исполняемого JAR
Вы можете собрать единый исполняемый JAR-файл, который содержит все необходимые зависимости, классы и ресурсы. Это делает его легким в загрузке, версионировании и развертывании сервиса как приложения на протяжении всего периода разработки, на различных средах и так далее.
Затем вы можете запустить JAR-файл:
Запуск сервиса
Если вы используете Gradle, вы можете запустить ваш сервис из командной строки:
Как вариант, вы можете запустить ваш сервис напрямую из Gradle примерно так:
Выходные данные отображены. Сервис должен быть поднят и запущен через несколько секунд.
Тестирование сервиса
Теперь, когда сервис поднят, поcетите http://localhost:8080/greeting и вы увидите:
Добавьте строковый параметр name в запрос http://localhost:8080/greeting?name=User. Обратите внимание, как значение атрибута content изменится с «Hello, World!» на «Hello User!»:
Это изменение показывает, что аннотация @RequestParam в GreetingController работает, как и ожидалось. Параметру name было дано значение по умолчанию «World», но оно может быть всегда переопределено через строку запроса.
Теперь, чтобы протестировать что CORS заголовки на месте и позволяют JavaScript клиенту из другого источника получить доступ к сервису, вам необходимо создать JavaScript клиент.
Для начала создайте простой JavaScript файл hello.js со следующим содержанием:
Этот скрипт использует jQuery для обработки ответа от сервиса http://localhost:8080/greeting. Скрипт загружается на странице index.html :
Чтобы запустить клиент, вам необходимо поднять web сервер. Spring Boot CLI (Command Line Interface) включает встроенный Tomcat сервер, который предоставляет простой подход к обработке web содержимого. Более подробную информацию об установке и использовании CLI смотрите в учебном материале Создание приложений с Spring Boot.
Для обработки статического содержимого вам необходимо создать минимальное количество кода. Приведенный ниже app.groovy скрипт достаточен для того, чтобы Spring Boot знал, что вы хотите запустить Tomcat:
Т.к. REST сервис уже запущен на localhost на 8080 порту, вам необходимо обязательно запустить клиента с другого сервера и/или порта. Это позволит избежать не только коллизий между двумя приложениями, но и быть уверенным в том, что клиентский код будет запущен с другого источника, отличного от источника сервиса. Для запуска клиента на localhost на 9000 порту, выполните:
Как только клиент запустится, откройте http://localhost:9000/ в вашем браузере, где вы увидите следующее:
Если ответ сервиса включает CORS заголовки, то на странице будут отображены ID и content. Но если CORS заголовки отсутствуют(или недостаточно определены для клиента), то браузер получит ошибку запроса и значения не будут отображены:
Поздравляем! Вы только что создали RESTful web-сервис, включающий Cross-Origin Resource Sharing с Spring.
Настройка CORS в Spring Security
В целях безопасности браузер запрещает JS-скрипту одного сайта обращаться на другой сайт без специального разрешения. Разрешение это реализуется с помощью технологии CORS (Cross-Origin Resource Sharing). Рассмотрим пример.
Когда возникает проблема
Создадим простое Spring Boot приложение с единственным Rest-контроллером:
В браузере запрос http://localhost:8080/api/hello выполняется успешно:

Теперь запустим на другом порту localhost:4200 Angular-проект (статика и js), он будет выполнять ajax-запросы к нашему контроллеру.
Мы запустили Spring Boot приложение на localhost:8080, а Angular-клиент на порту localhost:4200.
Откроем в браузере localhost:4200 — откроется страница Angular-клиента, которая содержит JavaScript-код, выполняющий запрос http://localhost:8080/api/hello. В консоли мы увидим ошибку, что-то вроде:

Страница, естественно, не отображается. У новичка, не знакомого с CORS-политикой браузера, возникает искушение отключить весь CORS в Spring Security. Но у нас он еще не включен. Потому что дело не в Spring Security, а в браузере. И CORS придется не отключить, а наоборот, включить. И настроить.
Включение CORS
Еще раз вернемся к ошибке:
Тут говорится, что в http-ответе на запрос http://localhost:8080/api/hello отсутствует заголовок Access-Control-Allow-Origin.
Что должно быть в http-ответе
Итак, чтобы браузер не выдавал ошибку, надо чтобы Spring Boot приложение явно указывало в http-ответе в заголовке Access-Control-Allow-Origin домен(ы), с которого разрешены запросы. То есть, чтобы не отсекать нашего клиента, запущенного на http://localhost:4200, в ответе должен содержаться такой заголовок:
Подразумевается, что Spring Boot приложение должно знать этот сайт http://localhost:4200 и давать ему разрешение на запросы с помощью вышеприведенного заголовка. Spring Boot приложение должно включать этот заголовок в ответ.
Если бы наш Angular-клиент находился на сайте myangularclient.com, то ему требовался бы соответственно такой заголовок:
А такой заголовок со звездочкой разрешит запросы всем сайтам:
Но последнее не безопасно.
Итак, займемся добавлением заголовка.
Настройка Spring Security
Для начала добавим Spring Security в проект:
Как только это сделано, включится принудительная аутентификация всех запросов по умолчанию, и при вводе в браузере запроса мы будем перенаправлены на страницу логина:

Исправим это, разрешив все запросы для всех пользователей (наш фокус — CORS, а не аутентификация):
Теперь в браузере запрос http://localhost:8080/api/hello выполняется — возвращается hello, а вот при выполнении запроса с клиента возникает та же ошибка. Исправим ее.
Настройка CORS
Для этого реализуем еще метод addCorsMappings() интерфейса WebMvcConfigurer:
В методе мы говорим, каким сайтам по каким url и какими методами можно делать запросы к нашему приложению, запущенному на 8080.
Теперь проверим, как это работает с Angular-клиента.
Проверка
На картинке всплывающая подсказка говорит, что мы обращаемся по запросу
Запрос и ответ содержат такие заголовки (запрос смотрите внизу, а ответ вверху, важное выделено красным):

Запрос
В запросе в заголовках Origin и Host содержится откуда и куда идет запрос. По ним приложение Spring Boot поймет, надо ли вообще включать в ответ заголовок Access-Control-Allow-Origin (если Origin и Host одинаковые, то не надо, проблемы в браузере в этом случае в принципе не возникнет).
Ответ
Далее наше Spring Boot приложение понимает, сайту http://localhost:4200 доступ разрешен (это мы настроили в методе addCorsMappings), так что в http-ответ оно включает такой заголовок:
Браузер видит по этому заголовку, что сайту http://localhost:4200 доступ разрешен и не зажёвывает ответ с выбросом ошибки в консоль, как это делал раньше, а передает его клиенту. Все ок.
Исходный код Spring Boot примера (без Angular-клиента) доступен на GitHub.
Настройка CORS в Spring Security: 8 комментариев
Спасибо огромное за статью!
Перерыл кучу ресурсов, перепробовал много всего и потратил много часов — и только предложенное здесь решение оказалось полноценным решением проблемы.
Да, автор этого сайта просто снимает всю головную боль! 🙂
Вопрос к автору:
Если заголовок Access-Control-Allow-Origin: * обрабатывается браузером, то как например будет идти обработка запроса любым другим Rest клиентом (например вредоносным с подделкой заголовков)? Как тогда защититься? Так же могут за кршпулить api сайта (если не включать безопасность, jwt например).





