Статьи

Поддержка CORS в Spring Framework

Автор Себастьян Делёз в блоге Spring 

По соображениям безопасности браузеры запрещают вызовы AJAX ресурсам, находящимся вне текущего источника. Например, когда вы проверяете свой банковский счет на одной вкладке, у вас может быть сайт evil.com на другой вкладке. Скрипты с сайта evil.com не должны отправлять запросы AJAX на API вашего банка (снятие денег с вашего счета!) С использованием ваших учетных данных.

Распределение ресурсов между источниками  (CORS) — это  спецификация W3C,  реализованная  большинством браузеров,  которая позволяет гибко указывать, какие типы запросов между доменами разрешены, вместо использования менее защищенных и менее мощных хаков, таких как IFrame или JSONP.

Недавно выпущенный  Spring Framework 4.2 RC1  обеспечивает  первоклассную поддержку CORS «  из коробки», предоставляя вам более простой и мощный способ его настройки, чем типичные   решения на основе фильтров .

Spring MVC предоставляет средства конфигурации высокого уровня, описанные ниже.

Контроллер метод настройки CORS

Вы можете добавить к своему  @RequestMapping методу аннотированного обработчика  @CrossOrigin аннотацию, чтобы включить для него CORS (по умолчанию  @CrossOrigin разрешены все источники и методы HTTP, указанные в  @RequestMapping аннотации):

@RestController
@RequestMapping("/account")
public class AccountController {

@CrossOrigin
@RequestMapping("/{id}")
public Account retrieve(@PathVariable Long id) {
// ...
}

@RequestMapping(method = RequestMethod.DELETE, value = "/{id}")
public void remove(@PathVariable Long id) {
// ...
}
}

Также возможно включить CORS для всего контроллера:

@CrossOrigin(origin = "http://domain2.com", maxAge = 3600)
@RestController
@RequestMapping("/account")
public class AccountController {

@RequestMapping("/{id}")
public Account retrieve(@PathVariable Long id) {
// ...
}

@RequestMapping(method = RequestMethod.DELETE, value = "/{id}")
public void remove(@PathVariable Long id) {
// ...
}
}

В этом примере поддержка CORS включена для обоих   методов retrieve() и  remove()методов-обработчиков, и вы также можете увидеть, как можно настроить конфигурацию CORS с помощью  @CrossOrigin атрибутов.

Вы даже можете использовать конфигурации CORS как на уровне контроллера, так и на уровне метода. Spring объединит оба атрибута аннотации для создания объединенной конфигурации CORS.

@CrossOrigin(maxAge = 3600)
@RestController
@RequestMapping("/account")
public class AccountController {

@CrossOrigin(origin = "http://domain2.com")
@RequestMapping("/{id}")
public Account retrieve(@PathVariable Long id) {
// ...
}

@RequestMapping(method = RequestMethod.DELETE, value = "/{id}")
public void remove(@PathVariable Long id) {
// ...
}
}

Глобальная конфигурация CORS

В дополнение к детальной конфигурации на основе аннотаций вы, вероятно, захотите также определить некоторую глобальную конфигурацию CORS. Это похоже на использование фильтров, но может быть объявлено в Spring MVC и объединено с детальной  @CrossOrigin конфигурацией. По умолчанию  разрешены все источники, и  GETHEAD и POSTметоды.

API-интерфейс глобальной конфигурации  изменился  после Spring Framework 4.2 RC1, поэтому обязательно используйте текущую сборку 4.2.0.BUILD-SNAPSHOT или следующую версию 4.2.0.RC2.

JavaConfig

Включение CORS для всего приложения так же просто, как:

@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {

@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**");
}
}

Вы можете легко изменить любые свойства, а также применить эту конфигурацию CORS только к определенному шаблону пути:

@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {

@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/api/**")
.allowedOrigins("http://domain2.com")
.allowedMethods("PUT", "DELETE")
.allowedHeaders("header1", "header2", "header3")
.exposedHeaders("header1", "header2")
.allowCredentials(false).maxAge(3600);
}
}

Пространство имен XML

Начиная с Spring Framework 4.2 RC2 также будет возможно настроить CORS с  пространством имен mvc XML .

Эта минимальная конфигурация XML включает CORS для  /** шаблона пути с теми же свойствами по умолчанию, что и у JavaConfig:

<mvc:cors>
<mvc:mapping path="/**" />
</mvc:cors>

Также возможно объявить несколько отображений CORS с настроенными свойствами:

<mvc:cors>

<mvc:mapping path="/api/**"
allowed-origins="http://domain1.com, http://domain2.com"
allowed-methods="GET, PUT"
allowed-headers="header1, header2, header3"
exposed-headers="header1, header2" allow-credentials="false"
max-age="123" />

<mvc:mapping path="/resources/**"
allowed-origins="http://domain1.com" />

</mvc:cors>

Как это работает?

Запросы CORS ( включая предполетные с помощью  OPTIONS метода ) автоматически отправляются различным  HandlerMappingзарегистрированным. Они обрабатывают предварительные запросы CORS и перехватывают простые и актуальные запросы CORS благодаря   реализации CorsProcessor (  по умолчанию DefaultCorsProcessor ) для добавления соответствующих заголовков ответов CORS (например  Access-Control-Allow-Origin). CorsConfiguration  позволяет указать, как должны обрабатываться запросы CORS: разрешенные источники, заголовки, методы и т. Д. Это может быть предоставлено различными способами:

  • AbstractHandlerMapping#setCorsConfiguration() позволяет указать  Map с несколькими CorsConfiguration,  сопоставленными с шаблонами пути, такими как /api/**
  • Подклассы могут предоставлять свои собственные  CorsConfiguration , переопределяя AbstractHandlerMapping#getCorsConfiguration(Object, HttpServletRequest) метод
  • Обработчики могут реализовать  CorsConfigurationSource интерфейс (как ResourceHttpRequestHandler сейчас), чтобы обеспечить  CorsConfiguration  для каждого запроса.

Интеграция Spring Boot

Поддержка CORS будет доступна в следующем выпуске Spring Boot 1.3 и уже доступна в сборках 1.3.0.BUILD-SNAPSHOT.

Если мелкозернистая конфигурация CORS уже идеально подходит для приложений Spring Boot, более  вероятно, что в Spring Boot 1.3 будет предоставлен более «удобный» способ настройки глобальной конфигурации CORS (на основе  объявления bean-компонента CorsConfiguration и выделенных свойств Spring Boot). Смотрите  эту проблему  для более подробной информации.

Как обычно, отзывы приветствуются!