taglibs sec hasrole spring-security spring-boot

spring security - hasrole - Usando mĂșltiples WebSecurityConfigurerAdapter en el arranque de primavera



sec:authorize thymeleaf (3)

Tengo 2 clases que extienden WebSecurityConfigurerAdapter . Y no podemos hacer que trabajen juntos.

La idea es la siguiente:

  1. Tenga un WebSecurityConfigurerAdapter que solo agregue un filtro personalizado a la cadena de seguridad. El filtro realiza alguna autenticación personalizada y guarda la Authentication en SecurityContext . Esto generalmente funciona bien. Configurado de la siguiente manera (importaciones omitidas):

@Order(1) @Configuration @EnableWebMvcSecurity public class BestSecurityConfig extends WebSecurityConfigurerAdapter { @Autowired private BestPreAuthenticationFilter ssoAuthenticationFilter; @Bean protected FilterRegistrationBean getSSOAuthenticationFilter() { FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(ssoAuthenticationFilter); // Avoid include to the default chain filterRegistrationBean.setEnabled(false); return filterRegistrationBean; } @Override protected void configure(HttpSecurity http) throws Exception { http .addFilterAfter(ssoAuthenticationFilter, SecurityContextPersistenceFilter.class); } @Configuration protected static class AuthenticationConfiguration extends GlobalAuthenticationConfigurerAdapter { @Autowired private BestAuthenticationProvider authenticationProvider; @Override public void configure(AuthenticationManagerBuilder auth) throws Exception { auth.authenticationProvider(authenticationProvider); } } }

  1. Quiero que lo anterior sea una clase de biblioteca que cualquiera puede incluir a través de @ComponentScan y obtener la autenticación personalizada ordenada. Obviamente, quieren proporcionar HttpSecurity personalizado para asegurar los puntos de edición. Intentando algo como:

@Configuration @EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true) @Order(SecurityProperties.ACCESS_OVERRIDE_ORDER) public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http .csrf().disable() .authorizeRequests() .antMatchers("/testUrl").hasRole("NON_EXISTING") .anyRequest().authenticated(); } }

Obviamente, la URL de prueba no debe ser accesible ya que mi usuario no es miembro de la función NON_EXISTING . Desafortunadamente ella es.

Si muevo la parte authorizeRequests() seguridad a la clase de configuración 1. Junto a agregar el filtro de seguridad, se bloquea el acceso como se esperaba. Pero en mi caso parece que la segunda configuración es ignorada.

También depuré los métodos de configure() y noté que HttpSecurity no es el mismo objeto que huele un poco.

Cualquier consejo, ¿cómo puedo hacer este trabajo muy apreciado.

Resumen de la meta:

  • tener un WebSecurityConfigurerAdapter que agrega el filtro y está oculto para el usuario de la biblioteca
  • Deje que el usuario defina su propia seguridad de punto final personalizada.

Bota de primavera 1.1.6-RELEASE


Así que una opción que acabo de encontrar es:

  1. Elimine la anotación @Configuration del primer bean

Y cambia el 2. a:

@Configuration @EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true) @Order(SecurityProperties.ACCESS_OVERRIDE_ORDER) public class SecurityConfig extends BestSecurityConfig { //Note the changed extend ! @Override protected void configure(HttpSecurity http) throws Exception { super.configure(http); // Merge of the 2 HTTP configurations http .csrf().disable() .authorizeRequests() .antMatchers("/testUrl").hasRole("NON_EXISTING") .anyRequest().authenticated(); } }

Cualquier comentario sobre si este es el enfoque correcto o incorrecto muy apreciado

Edit: Después de algunos años, todavía no encontraba otra manera, pero me gusta cada vez más. Incluso en el caso predeterminado, usted extiende el resumen WebSecurityConfigurerAdapter no hay ninguna razón por la que alguna otra capa de abstracción no pueda proporcionar otra extensión abstracta que proporcione valores predeterminados significativos.


Fundé (en mi opinión) una forma más limpia de estructurar algunas configuraciones predeterminadas y simplificar la integración en nuevos proyectos mediante el uso de DSL personalizadas .

Lo estoy usando para configurar los filtros de autenticación JWT, pero creo que un filtro CORS es más simple y didáctico:

public class CustomCorsFilterDsl extends AbstractHttpConfigurer<CustomCorsFilterDsl, HttpSecurity> { @Override public void init(HttpSecurity http) throws Exception { //your init code here, no needed in this case } @Override public void configure(HttpSecurity http) throws Exception { CorsFilter corsFilter = corsFilter(corsProperties); http.addFilterBefore(corsFilter, UsernamePasswordAuthenticationFilter.class); } private CorsFilter corsFilter(CorsProperties corsProperties) { UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); CorsConfiguration config = new CorsConfiguration(); config.setAllowCredentials(true); config.addAllowedOrigin("http://localhost:9000"); config.addAllowedHeader("*"); config.addAllowedMethod("GET, POST, PUT, PATCH, DELETE"); source.registerCorsConfiguration("/**", config); return new CorsFilter(source); } public static CustomCorsFilterDsl dsl() { return new CustomCorsFilterDsl(); } }

Y en su WebSecurityConfig puede usarlo así:

@Configuration @EnableWebSecurity public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http .csrf().disable() .exceptionHandling() .and() .sessionManagement() .sessionCreationPolicy(SessionCreationPolicy.STATELESS) .and() .authorizeRequests() .antMatchers("/foo/**").permitAll() //... your configurations .antMatchers("/**").authenticated() .and() .apply(CustomCorsFilterDsl.dsl()); } }

Y logró su objetivo de tener bibliotecas con configuraciones predeterminadas independientes del código de sus proyectos, de una manera más clara, porque puede visualizar en la entrada WebSecurityConfig del proyecto una entrada personalizada de CORS.


Otra solución que usamos para esto.

Definir una interfaz especial.

public interface ServiceWebSecurityConfigurer { void configure(HttpSecurity http) throws Exception; }

Entonces ten solo un ConfigurerAdapter:

public class MyConfigurerAdapter extends WebSecurityConfigurerAdapter { @Autowired(required = false) ServiceWebSecurityConfigurer serviceSecConfig; public void configure(HttpSecurity http) throws Exception { http.authorizeRequests(). // whatever if (serviceSecConfig != null) serviceSecConfig.configure(http); http.authorizeRequests(). // whatever } }

y luego simplemente implemente ServiceWebSecurityConfigurer en otro lugar cuando sea necesario. También puede haber múltiples implementaciones, solo autowire como lista e iteración y utilícelas todas en su configuración principal.