No tienes acceso a esta clase

¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera

Configuración de CORS en Spring Security para APIs

8/23
Recursos

¿Qué es CORS y cómo afecta a tu aplicación?

Cuando trabajamos en proyectos web divididos en frontend y backend, a menudo tratamos con el intercambio de recursos entre diferentes orígenes. Esto es especialmente común cuando la aplicación frontend se ejecuta desde un dominio y el backend desde otro. Aquí es donde entra CORS (Cross-Origin Resource Sharing), un sistema crucial para permitir o restringir tales interacciones por razones de seguridad.

Por defecto, los frameworks como Spring bloquean estas peticiones cruzadas. Esto puede ser un obstáculo si, por ejemplo, nuestro frontend se ejecuta en localhost:4200 usando Angular, y nuestro API backend corre en localhost:8080. Afortunadamente, Spring Security ofrece mecanismos para configurar y habilitar CORS, permitiendo así que aplicaciones de frontend puedan comunicarse con APIs alojadas en diferentes dominios.

¿Cómo se implementa CORS en Spring Security?

Para gestionar CORS en una aplicación Spring, es necesario modificar algunas configuraciones del backend. Esto asegura que tu aplicación pueda reconocer y permitir peticiones legítimas desde otros orígenes.

  1. Deshabilitar CSRF y habilitar CORS:

    • Desde el backend, después de deshabilitar CSRF (Cross-Site Request Forgery), habilitamos CORS usando cors().and(). Esto asegura que las configuraciones de CORS y las peticiones autorizadas se consideren.
  2. Anotación a métodos específicos:

    • Utiliza la anotación @CrossOrigin en los métodos de tus controladores para permitir accesos desde orígenes específicos. Por ejemplo:

      @CrossOrigin(origins = "http://localhost:4200")
      public ResponseEntity<Pizza> getPizzas() {
          // Tu lógica aquí
      }
      
  3. Implementación de una configuración global:

    • Para evitar anotar cada método individualmente, puedes definir una configuración global. Esto se realiza creando una nueva clase configuradora:

      @Configuration
      public class CorsConfig {
          @Bean
          public CorsConfigurationSource corsConfigurationSource() {
              CorsConfiguration configuration = new CorsConfiguration();
              configuration.setAllowedOrigins(Arrays.asList("http://localhost:4200"));
              configuration.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE"));
              configuration.setAllowedHeaders(Arrays.asList("*"));
              UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
              source.registerCorsConfiguration("/**", configuration);
              return source;
          }
      }
      

¿Qué beneficios trae la configuración global de CORS?

Optar por una configuración global de CORS en un proyecto tiene varias ventajas:

  • Simplicidad y Mantenimiento: Centralizar las configuraciones hace que el mantenimiento del código sea más sencillo. Cualquier cambio en las políticas de origen solo requiere una modificación en el archivo de configuración.

  • Consistencia: Proporciona una manera uniforme de gestionar el acceso a todos los controladores y métodos, asegurando una protección constante y sin omisiones.

  • Escalabilidad: Facilita la ampliación de las políticas de acceso conforme el proyecto crece, simplificando la adición de nuevos métodos y controladores que necesitan el mismo manejo de políticas de acceso.

¿Cómo asegurar un despliegue exitoso?

Después de implementar la configuración de CORS, es vital verificar el funcionamiento de la aplicación:

  1. Inicializa la aplicación: Lanza la aplicación backend y revisa que la configuración de CORS se carga correctamente. Esto se puede verificar revisando las trazas del servidor.

  2. Validación de Seguridad: Siempre asegúrate de que las políticas de seguridad no han sido alteradas inadvertidamente. Uso de herramientas como Postman para comprobar la autenticación de peticiones asegura que todo funciona como esperabas.

  3. Prueba desde el frontend: Finalmente, accede al frontend y realiza pruebas desde diferentes entornos (navegadores, dispositivos) para confirmar que las peticiones cross-origin funcionan y se manejan correctamente.

Con esta configuración, Spring Security te permite gestionar las políticas de acceso entre orígenes de manera eficiente. ¡Sigue aprendiendo y explorando las funcionalidades que estos marcos pueden ofrecer a tus proyectos!

Aportes 15

Preguntas 4

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad?

Muy importante el CORS en Proyectos reales.
Si toca implementar Back, asegúrense de utilizarlos, a veces quien hace los servicios consume o hace pruebas desde Postman o otro programa en Java, ahi no les marcara error de CORS como una aplicación front desde el navegador web, y pueden tener la errorea idea de que están bien y perdiendo tiempo con el otro equipo verificando donde esta el problema.

Errores de CORS --> 100% Back.

Por si algún compañero tiene problemas al aplicar la configuración de cors en la clase SecurityConfig, ya que intellij dice que esta deprecado. Pueden utilizar el siguiente código:

@Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http.authorizeHttpRequests(customizeRequests -> {
                    customizeRequests.anyRequest().authenticated();
                }).csrf(AbstractHttpConfigurer::disable).cors(Customizer.withDefaults())
                .httpBasic(Customizer.withDefaults());
        return http.build();
    }

CORS
=Cross-Origin Resource Sharing
=Uso compartido de recursos entre orígenes

Hola compañeros, tengo unas ganas de hacer una implemetación de front end al proyecto asi que les traigo un HTML (index.html) y Js (main.js) para los que tambien tienen ganas de hacer eso y ir probando el proyecto puedan hacerlo ❤️

HTML (index.html)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Pizza</title>
</head>
<body>
    <div id="pizzas"></div>  
    <script src="main.js"></script>
</body>
</html>

JavaScript (main.js)

const urlAPI = "";
const APIKey = "XXXXXXXXXXXXXXXXXXXX";

async function pizzasGET () {
    const response = await fetch(urlAPI,
        {
            method: 'GET',
            headers: {
                'Content-Type': 'application/json',
                'Authorization': APIKey,
            },
        });
    const datos = await response.json();

    console.log(datos);
    const pizzaContent = document.getElementById("pizzas");
    pizzaContent.textContent = JSON.stringify(datos);
}

pizzasGET();
```js @Configuration public class SecurityConfig { @Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { http .csrf(AbstractHttpConfigurer::disable) .cors(Customizer.withDefaults()) .authorizeHttpRequests(customizeRequests -> { customizeRequests .anyRequest() .authenticated(); }) .httpBasic(Customizer.withDefaults()); return http.build(); } } ```

Aqui les dejo el html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Pizza</title>
</head>
<body>
  <code id="pizzas">

  </code>
    <script>
      const pizzaContent=document.getElementById("pizzas")
const url=""
const auth="Basic dXNlcjozM2EzNGM4Ny0yMzZmLTQ1YzUtYWU4NC1mZGY3MmJhZWY3NzY="
fetch(url, {
  "headers": {
    "Authorization": auth
  }})
    .then(response => response.json())
    .then(result => {
      console.log(result)
      pizzaContent.textContent = JSON.stringify(result);
    });
    </script>
</body>
</html>

normalmente yo solo aqui aplicada lo de los CORS XD:

@CrossOrigin(origins = { “*” })
@RestController
@RequestMapping("/api")
public class ClientRestController {

ahora ya se que lo puedo hacer mas profesional jajaj xd

Código funcionando sin problemas de metodos deprecados y con cors funcionando ```java package com.auth.Center.web.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.Customizer; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer; import org.springframework.security.web.SecurityFilterChain; //indica que la clase puede contener métodos de bean. Un método de bean es un método que Spring ejecuta para registrar // un objeto en su contenedor de inversión de control (IoC @Configuration //Agrega varias características de seguridad, como la protección CSRF, la autenticación y la autorización. @EnableWebSecurity public class SecurityConfig { // indica que el método que sigue debe ser ejecutado por Spring para registrar un bean en su contenedor IoC @Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { http //desactivando la protección CSRF (Cross-Site Request Forgery) // es una característica de seguridad que ayuda a prevenir ciertos tipos de ataques, pero en algunos casos, puedes querer desactivarla .csrf(AbstractHttpConfigurer::disable) //habilitando la configuración de CORS (Cross-Origin Resource Sharing) .cors(Customizer.withDefaults()) //indicando que todas las solicitudes HTTP deben estar autenticadas .authorizeHttpRequests(auth -> auth.anyRequest().authenticated()) //habilitando la autenticación básica HTTP .httpBasic(Customizer.withDefaults()); // construyendo la configuración de seguridad y devolviéndola return http.build(); } } ```
Para Angular 19 debes ponerle la configuracion de la Basic Auth con user y password: ![](https://static.platzi.com/media/user_upload/image-0ff5b865-a1d4-48f3-a0a9-5dff6049e73b.jpg)
excelente explicacion profesor
estoy usando java 17 y spring 3.2.5 y spring security 6.2.4 logre que me funcionara asi @Bean *public SecurityFilterChain* filterChain(HttpSecurity http) *throws* Exception{ http.cors(cors -> cors.configurationSource(corsConfigurationSource())).authorizeHttpRequests(authorize -> authorize .anyRequest().authenticated()).csrf((csrf) -> csrf.ignoringRequestMatchers("/api/\*")).httpBasic(*withDefaults*()); *return* http.build(); } @Bean *public CorsConfigurationSource* corsConfigurationSource() { CorsConfiguration config = *new* CorsConfiguration().applyPermitDefaultValues(); config.setAllowedMethods(Arrays.*asList*("GET", "POST", "PUT", "DELETE", "PATCH")); config.setAllowCredentials(*false*); config.setAllowedHeaders(Arrays.*asList*("Authorization", "Cache-Control", "Content-Type", "X-Frame-Options")); UrlBasedCorsConfigurationSource source = *new* UrlBasedCorsConfigurationSource(); source.registerCorsConfiguration("/\*\*", config); *return* source; }
```java @Bean public CorsConfigurationSource corsConfigurationSource() { CorsConfiguration config = new CorsConfiguration().applyPermitDefaultValues(); config.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE", "PATCH")); config.setAllowCredentials(false); config.setAllowedHeaders(Arrays.asList("Authorization", "Cache-Control", "Content-Type", "X-Frame-Options")); UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); source.registerCorsConfiguration("/\*\*", config); return source; } ```
CORS Cross-Origin Resource Sharing: Es un mecanismo para integrar aplicaciones. Define una forma para que las aplicaciones web cliente que se cargan en un dominio interactúen con recursos en un dominio diferente.
@Configuration public class SecurityConfig { @Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { http .csrf(AbstractHttpConfigurer::disable) .cors(Customizer.*withDefaults*()) .authorizeHttpRequests(customizeRequests -> { customizeRequests .anyRequest() .authenticated(); }) .httpBasic(Customizer.*withDefaults*()); return http.build(); } }
@CrossOrigin en el controlador se usa en algun proyecto real, es viable para la arquitectura del sistema ?