Saltar al contenido

¿Cómo agrego un filtro a spring-security basado en un @Profile?

este problema se puede solucionar de variadas maneras, por lo tanto te dejamos la respuesta más completa en nuestra opinión.

Solución:

Del artículo sobre la arquitectura Spring Security:

Spring Security se instala como un filtro único en la cadena, y su tipo concreto es FilterChainProxy, por razones que se harán evidentes pronto. En una aplicación Spring Boot, el filtro de seguridad es un @Bean en ApplicationContext y se instala de manera predeterminada para que se aplique a cada solicitud.

Puede haber múltiples cadenas de filtros, todas administradas por Spring Security en el mismo FilterChainProxy de nivel superior y todas desconocidas para el contenedor. El filtro Spring Security contiene una lista de cadenas de filtros y envía una solicitud a la primera cadena que coincida.

Tenga en cuenta también que:

El hecho de que todos los filtros internos de Spring Security sean desconocidos para el contenedor es importante, especialmente en una aplicación Spring Boot, donde todos los @Beans de tipo Filter se registran automáticamente con el contenedor de forma predeterminada. Entonces, si desea agregar un filtro personalizado a la cadena de seguridad, debe no convertirlo en un @Bean o envolverlo en un FilterRegistrationBean que deshabilite explícitamente el registro del contenedor.

Entonces, cuando define un filtro como un bean Spring, se registra con el contenedor de servlets automáticamente, pero no con la cadena de filtros Spring Security. Es por eso que debe agregarlo a la cadena Spring Security explícitamente usando el método addFilter. También debe deshabilitar el registro automático en el contenedor de servlet o el filtro se llamará dos veces.

Ver también:

  • 75.3 Adición de un servlet, filtro o escucha a una aplicación
  • ¿Cuál es la implicación de agregar @Component al filtro Spring Security personalizado?

En cuanto a perfiles hay al menos dos formas de hacer lo que necesitas:

  1. Extienda AbstractHttpConfigurer y mueva allí la configuración de seguridad común. Después de eso, cree una configuración de seguridad separada para cada perfil:

    @Configuration
    @EnableWebSecurity(debug = true)
    @EnableGlobalMethodSecurity(prePostEnabled = true, jsr250Enabled = true, securedEnabled = true)
    public class SecurityConfiguration 
    
        /**
         * Development security configuration.
         */
        @Profile("dev")
        @Configuration
        public static class DevSecurityConfiguration extends WebSecurityConfigurerAdapter 
    
            @Bean
            public FilterRegistrationBean userIdAuthenticationFilter() 
                // ...
            
    
            @Override
            protected void configure(HttpSecurity http) throws Exception 
                http.apply(commonSecurityConfiguration())
                        .and().addFilter(userIdAuthenticationFilter().getFilter());
            
        
    
        /**
         * Production security configuration.
         */
        @Profile("!dev")
        @Order(1)
        @Configuration
        public static class ProdSecurityConfiguration extends WebSecurityConfigurerAdapter 
    
            @Bean
            public FilterRegistrationBean jwtAuthenticationFilter() 
                // ...
            
    
            @Override
            protected void configure(HttpSecurity http) throws Exception 
                http.apply(commonSecurityConfiguration())
                        .and().addFilter(jwtAuthenticationFilter().getFilter());
            
        
    
    
        /**
         * Common security configuration reused by all profiles.
         */
        public static class CommonSecurityConfiguration
                extends AbstractHttpConfigurer 
    
            @Override
            public void init(HttpSecurity http) throws Exception 
                // Your basic configuration here:
                // http.cors().and()
                // ...
            
    
            public static CommonSecurityConfiguration commonSecurityConfiguration() 
                return new CommonSecurityConfiguration();
            
        
    
    

    Véase también el ejemplo en la documentación.

  2. Inyecte el objeto Environment y verifique el perfil actual:

    @Configuration
    @EnableWebSecurity(debug = true)
    @EnableGlobalMethodSecurity(prePostEnabled = true, jsr250Enabled = true, securedEnabled = true)
    public class SecurityConfiguration extends WebSecurityConfigurerAdapter 
    
        private final Environment environment;
    
        public SecurityConfiguration(Environment environment) 
            this.environment = environment;
        
    
        @Profile("dev")
        @Bean
        public FilterRegistrationBean userIdAuthenticationFilter() 
            // ...
        
    
        @Profile("!dev")
        @Bean
        public FilterRegistrationBean jwtAuthenticationFilter() 
            // ...
        
    
        @Override
        protected void configure(HttpSecurity http) throws Exception 
            // Your basic configuration here:
            // http.cors().and()
            // ...
    
            if (environment.acceptsProfiles("dev")) 
                http.addFilter(userIdAuthenticationFilter().getFilter());
             else 
                http.addFilter(jwtAuthenticationFilter().getFilter());
            
        
    
    

    Alternativamente, puede usar la propiedad de la aplicación en lugar del perfil para esto.

Al final de la web puedes encontrar las aclaraciones de otros administradores, tú aún tienes la opción de mostrar el tuyo si lo deseas.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *