Spring MVC permite usted debe manejar CORS (intercambio de recursos entre orígenes).
Introducción
Por razones de seguridad, los navegadores prohíben las llamadas AJAX a recursos fuera del origen actual. Por ejemplo, es posible que tengas tu cuenta bancaria en una pestaña y evil.com en otra. Los scripts de evil.com no deberían poder realizar solicitudes AJAX a la API de su banco con sus credenciales; por ejemplo, ¡retirar dinero de su cuenta!
El intercambio de recursos entre orígenes (CORS) es especificación W3C implementada en la mayoría de los navegadores, lo que le permite determinar qué solicitudes entre dominios están permitidas, en lugar de utilizar soluciones alternativas menos seguras y menos potentes basadas en IFRAME o JSONP.
Procesamiento
La especificación CORS distingue entre solicitudes de verificación previa, simples y reales. Para comprender cómo funciona CORS, puede leer este artículo. otras cosas, o consulte la especificación para obtener más detalles.
Las implementaciones HandlerMapping
de Spring MVC
proporcionan soporte CORS nativo. Después de asignar con éxito una solicitud a un controlador, las implementaciones
de HandlerMapping
verifican la configuración CORS para esa solicitud y controlador y toman medidas
adicionales. Las solicitudes preliminares se procesan directamente, mientras que las solicitudes CORS simples y
reales se interceptan, validan y se establecen los encabezados de respuesta CORS requeridos.
Para permitir
solicitudes entre diferentes orígenes (es decir, el encabezado Origin
está presente y es diferente
del host de solicitud), debe proporcionar alguna configuración CORS declarada explícitamente. Si no se encuentra
una configuración CORS adecuada, se rechazan las solicitudes de verificación previa. Las respuestas a
solicitudes CORS simples y reales no tienen encabezados CORS agregados y, por lo tanto, los navegadores las
rechazan.
Cada HandlerMapping
puede ser configurado individualmente usando asignaciones
CorsConfiguration
basadas en patrones de URL. En la mayoría de los casos, las aplicaciones utilizan una
configuración Java MVC o un espacio de nombres XML para declarar dichas asignaciones, lo que da como resultado que
todas las instancias de
HandlerMapping
reciban un único mapa global.
Puedes combinar CORS global configuración en el
nivel
HandlerMapping
con un ajuste CORS más detallado en el nivel del controlador. Por ejemplo, los
controladores anotados pueden usar anotaciones @CrossOrigin
a nivel de clase o método (otros
controladores pueden implementar CorsConfigurationSource
).
Las reglas para combinar reglas
globales y la configuración local suelen ser aditivas; por ejemplo, todas las fuentes globales y todas las locales.
Para aquellos atributos donde solo se puede aceptar un valor, como allowCredentials
y
maxAge
, el valor local anula el global. Para obtener más información, consulte la sección sobre CorsConfiguration#combine(CorsConfiguration)
.
Para obtener más información sobre el código fuente o la configuración avanzada, consulte el código:
CorsConfiguration
CorsProcessor
,DefaultCorsProcessor
AbstractHandlerMapping
@CrossOrigin
Anotación @CrossOrigin
permite consultas entre diferentes fuentes a métodos de
controlador anotados, como se muestra en el siguiente ejemplo:
@RestController
@RequestMapping("/account")
public class AccountController {
@CrossOrigin
@GetMapping("/{id}")
public Account retrieve(@PathVariable Long id) {
// ...
}
@DeleteMapping("/{id}")
public void remove(@PathVariable Long id) {
// ...
}
}
@RestController
@RequestMapping("/account")
class AccountController {
@CrossOrigin
@GetMapping("/{id}")
fun retrieve(@PathVariable id: Long): Account {
// ...
}
@DeleteMapping("/{id}")
fun remove(@PathVariable id: Long) {
// ...
}
}
De forma predeterminada, @CrossOrigin
permite:
Todas las fuentes.
Todos los encabezados.
Todos los métodos HTTP con los que está asociado el método del controlador.
allowCredentials
no está habilitado de forma predeterminada, ya que esto establece el nivel de
confianza en el que se divulga la información confidencial del usuario (como cookies y tokens CSRF), por lo
que solo debe usarse en los casos en que sea realmente necesario. Si está habilitado, entonces se debe
configurar allowOrigins
para uno o más dominios específicos (pero no el valor especial "*"
)
o, alternativamente, la propiedad enableOriginPatterns se puede usar para asignaciones. frente a un conjunto
dinámico de fuentes.
maxAge
se establece en 30 minutos.
La @CrossOrigin
anotación se admite en el nivel de clase y también se heredan todos los métodos,
como se muestra en el siguiente ejemplo:
@CrossOrigin(origins = "https://domain2.com", maxAge = 3600)
@RestController
@RequestMapping("/account")
public class AccountController {
@GetMapping("/{id}")
public Account retrieve(@PathVariable Long id) {
// ...
}
@DeleteMapping("/{id}")
public void remove(@PathVariable Long id) {
// ...
}
}
@CrossOrigin(origins = ["https://domain2.com"], maxAge = 3600)
@RestController
@RequestMapping("/account")
class AccountController {
@GetMapping("/{id}")
fun retrieve(@PathVariable id: Long): Account {
// ...
}
@DeleteMapping("/{id}")
fun remove(@PathVariable id: Long) {
// ...
}
Puede utilizar la anotación @CrossOrigin
tanto a nivel de clase como de método, como se muestra
en el siguiente ejemplo:
@CrossOrigin(maxAge = 3600)
@RestController
@RequestMapping("/account")
public class AccountController {
@CrossOrigin("https://domain2.com")
@GetMapping("/{id}")
public Account retrieve(@PathVariable Long id) {
// ...
}
@DeleteMapping("/{id}")
public void remove(@PathVariable Long id) {
// ...
}
}
@CrossOrigin(maxAge = 3600)
@RestController
@RequestMapping("/account")
class AccountController {
@CrossOrigin("https://domain2.com")
@GetMapping("/{id}")
fun retrieve(@PathVariable id: Long): Account {
// ...
}
@DeleteMapping("/{id}")
fun remove(@PathVariable id: Long) {
// ...
}
}
Configuración global
Además del ajuste fino en el controlador A nivel de método, probablemente necesitará definir la configuración
global de CORS. Puede configurar asignaciones CorsConfiguration
basadas en URL individualmente
para cualquier HandlerMapping
. Sin embargo, la mayoría de las aplicaciones utilizan la
configuración MVC en Java o el espacio de nombres MVC en XML para hacer esto.
De forma predeterminada, la configuración global permite lo siguiente:
Todas las fuentes.
Todos los encabezados.
Métodos
GET
,HEAD
yPOST
.
allowCredentials
no está habilitado de forma predeterminada porque establece el nivel de
confianza en el que se información del usuario (como cookies y tokens CSRF), por lo que solo debe usarse en
los casos en que sea realmente necesario. Si está habilitado, entonces se debe configurar
allowOrigins
para uno o más dominios específicos (pero no el valor especial "*"
)
o, alternativamente, la propiedad enableOriginPatterns se puede usar para asignaciones. contra un conjunto
dinámico de fuentes.
maxAge
se establece en 30 minutos.
Configuración de Java
Para habilitar CORS en la configuración de Java MVC, puede utilizar la devolución de llamada
CorsRegistry
como se muestra en el siguiente ejemplo:
@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/api/**")
.allowedOrigins("https://domain2.com")
.allowedMethods("PUT", "DELETE")
.allowedHeaders(" header1", "header2", "header3")
.exposedHeaders("header1", "header2")
.allowCredentials(true).maxAge(3600);
// Agregar más visualizaciones...
}
}
@Configuration
@EnableWebMvc
class WebConfig : WebMvcConfigurer {
override fun addCorsMappings(registry: CorsRegistry) {
registry.addMapping("/api/**")
.allowedOrigins("https://domain2.com")
.allowedMethods("PUT", "DELETE") .allowedHeaders("header1 ", "header2", "header3")
.exposedHeaders("header1", "header2")
.allowCredentials(true).maxAge(3600)
// Agregar más vistas...
}
}
Configuración XML
Para habilitar CORS en un espacio de nombres XML, puede utilizar el elemento
<mvc:cors>
, como se muestra en la siguiente ejemplo:
<mvc:cors>
<mvc:mapping path="/api/**"
allowed-origins="https://domain1.com, https://domain2.com"
allowed-methods="GET, PUT"
allowed-headers="header1, header2, header3"
exposed-headers="header1, header2" allow-credentials="true"
max-age="123" />
<mvc:mapping path="/resources/**"
allowed-origins="https://domain1.com" />
</mvc:cors>
filtro CORS
Puede aplicar compatibilidad con CORS a través del CorsFilter
.
CorsFilter
con Spring Security,
tenga en cuenta que Spring Security proporciona built -en soporte CORS.
Para configurar un filtro, pase CorsConfigurationSource
a su constructor, como se muestra en
el siguiente ejemplo:
CorsConfiguration config = new CorsConfiguration();
// Quizás...
// config.applyPermitDefaultValues()
config.setAllowCredentials(true);
config.addAllowedOrigin("https://domain1.com");
config.addAllowedHeader("*");
config.addAllowedMethod("*");
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", config);
CorsFilter filter = new CorsFilter(source);
val config = CorsConfiguration()
// Posiblemente...
// config.applyPermitDefaultValues()
config.allowCredentials = true config.addAllowedOrigin("https://domain1.com")
config.addAllowedHeader("*") config.addAllowedMethod("*")
val source = UrlBasedCorsConfigurationSource()
source.registerCorsConfiguration("/**", config)
val filter = CorsFilter(source)