Sirviendo recursos web estáticos en la aplicación Spring Boot & Spring Security

Estoy tratando de desarrollar la aplicación web Spring Boot y asegurarla usando la configuración Spring de seguridad java.

Después de colocar mis recursos web estáticos en ‘ src / main / resources / public ‘ como se aconseja aquí en el blog de Spring , puedo obtener los recursos estáticos. es decir, al tocar https://localhost/test.html en el navegador sirve el contenido html.

Problema

Después de habilitar Spring Security, presionar la URL del recurso estático requiere autenticación.

Mi configuración de Spring Spring Java se ve así: –

 @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off http. authorizeRequests() .antMatchers("/","/public/**", "/resources/**","/resources/public/**") .permitAll() .antMatchers("/google_oauth2_login").anonymous() .anyRequest().authenticated() .and() .formLogin() .loginPage("/") .loginProcessingUrl("/login") .defaultSuccessUrl("/home") .and() .csrf().disable() .logout() .logoutSuccessUrl("/") .logoutUrl("/logout") // POST only .and() .requiresChannel() .anyRequest().requiresSecure() .and() .addFilterAfter(oAuth2ClientContextFilter(),ExceptionTranslationFilter.class) .addFilterAfter(googleOAuth2Filter(),OAuth2ClientContextFilter.class) .userDetailsService(userService); // @formatter:on } 

¿Cómo debo configurar antMatchers para permitir que los recursos estáticos se coloquen dentro de src / main / resources / public?

Hay un par de cosas que debe tener en cuenta:

  • Los matchers Ant coinciden con la ruta de solicitud y no con la ruta del recurso en el sistema de archivos.
  • Los recursos colocados en src/main/resources/public servirán desde la raíz de su solicitud. Por ejemplo, src/main/resources/public/hello.jpg se serviría desde http://localhost:8080/hello.jpg

Esta es la razón por la que su configuración de emparejador actual no ha permitido el acceso a los recursos estáticos. Para que /resources/** funcione, debe colocar los recursos en src/main/resources/public/resources y acceder a ellos en http://localhost:8080/resources/your-resource .

Como está utilizando Spring Boot, es posible que desee considerar el uso de sus valores predeterminados en lugar de agregar una configuración adicional. Spring Boot, de forma predeterminada, permitirá el acceso a /css/** , /js/** , /images/** y /**/favicon.ico . Podría, por ejemplo, tener un archivo llamado src/main/resources/public/images/hello.jpg y, sin agregar ninguna configuración adicional, sería accesible en http://localhost:8080/images/hello.jpg sin tener que iniciar sesión. Puede ver esto en acción en la muestra de seguridad del método web donde se permite el acceso al archivo CSS de Bootstrap sin ninguna configuración especial.

  @Override public void configure(WebSecurity web) throws Exception { web .ignoring() .antMatchers("/resources/**"); // #3 } 

Ignore cualquier solicitud que comience con “/ resources /”. Esto es similar a la configuración de http @ security = none cuando se utiliza la configuración del espacio de nombres XML.

Aquí está la solución definitiva, después de más de 20 horas de investigación.

Paso 1. Agrega ‘MvcConfig.java’ a tu proyecto.

 import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.EnableWebMvc; import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; @Configuration public class MvcConfig extends WebMvcConfigurerAdapter { @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { registry .addResourceHandler("/resources/**") .addResourceLocations("/resources/"); } } 

Paso 2. Agregue la configure(WebSecurity web) a su clase SecurityConfig

 @Override public void configure(WebSecurity web) throws Exception { web .ignoring() .antMatchers("/resources/**"); } 

Paso 3. Coloque todos los recursos estáticos en webapp / resources / ..

Si está usando webjars. http.authorizeRequests().antMatchers("/webjars/**").permitAll(); agregar esto en su método de configure : http.authorizeRequests().antMatchers("/webjars/**").permitAll();

Asegúrate de que esta sea la primera statement. Por ejemplo:

 @Configuration @EnableWebSecurity public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests().antMatchers("/webjars/**").permitAll(); http.authorizeRequests().anyRequest().authenticated(); http.formLogin() .loginPage("/login") .failureUrl("/login?error") .usernameParameter("email") .permitAll() .and() .logout() .logoutUrl("/logout") .deleteCookies("remember-me") .logoutSuccessUrl("/") .permitAll() .and() .rememberMe(); } 

También necesitarás tener esto para tener webjars habilitados:

 @Configuration public class MvcConfig extends WebMvcConfigurerAdapter { ... @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/"); } ... } 
 @Configuration @EnableWebSecurity public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { String[] resources = new String[]{ "/", "/home","/pictureCheckCode","/include/**", "/css/**","/icons/**","/images/**","/js/**","/layer/**" }; http.authorizeRequests() .antMatchers(resources).permitAll() .anyRequest().authenticated() .and() .formLogin() .loginPage("/login") .permitAll() .and() .logout().logoutUrl("/404") .permitAll(); super.configure(http); } } 

Esta puede ser una respuesta (para el arranque de spring 2) y una pregunta al mismo tiempo. Parece que en el arranque de spring 2 combinado con la seguridad de spring todo (significa cada ruta / antipatía) está protegido por defecto si utiliza un mecanismo de seguridad individual extendido desde

 WebSecurityConfigurerAdapter 

Si no usa un mecanismo de seguridad individual, ¿todo está como estaba?

En las versiones anteriores de arranque de spring (1.5 y siguientes), como dice Andy Wilkinson en su respuesta anterior, los lugares como public/** or static/** están permitidos por defecto.

Por lo tanto, para resumir esta pregunta / respuesta, si está utilizando Spring Boot 2 con seguridad de spring y tiene un mecanismo de seguridad individual, debe permitir el acceso exclusivo a contenidos estáticos colocados en cualquier ruta. Al igual que:

 @Configuration public class SpringSecurityConfiguration extends WebSecurityConfigurerAdapter { private final ThdAuthenticationProvider thdAuthenticationProvider; private final ThdAuthenticationDetails thdAuthenticationDetails; /** * Overloaded constructor. * Builds up the needed dependencies. * * @param thdAuthenticationProvider a given authentication provider * @param thdAuthenticationDetails given authentication details */ @Autowired public SpringSecurityConfiguration(@NonNull ThdAuthenticationProvider thdAuthenticationProvider, @NonNull ThdAuthenticationDetails thdAuthenticationDetails) { this.thdAuthenticationProvider = thdAuthenticationProvider; this.thdAuthenticationDetails = thdAuthenticationDetails; } /** * Creates the AuthenticationManager with the given values. * * @param auth the AuthenticationManagerBuilder */ @Autowired public void configureGlobal(AuthenticationManagerBuilder auth) { auth.authenticationProvider(thdAuthenticationProvider); } /** * Configures the http Security. * * @param http HttpSecurity * @throws Exception a given exception */ @Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() .requestMatchers(PathRequest.toStaticResources().atCommonLocations()).permitAll() .antMatchers("/management/**").hasAnyAuthority(Role.Role_Engineer.getValue(), Role.Role_Admin.getValue()) .antMatchers("/settings/**").hasAnyAuthority(Role.Role_Engineer.getValue(), Role.Role_Admin.getValue()) .anyRequest() .fullyAuthenticated() .and() .formLogin() .authenticationDetailsSource(thdAuthenticationDetails) .loginPage("/login").permitAll() .defaultSuccessUrl("/bundle/index", true) .failureUrl("/denied") .and() .logout() .invalidateHttpSession(true) .logoutSuccessUrl("/login") .logoutUrl("/logout") .and() .exceptionHandling() .accessDeniedHandler(new CustomAccessDeniedHandler()); } 

}

Tenga en cuenta esta línea de código, que es nueva:

 .requestMatchers(PathRequest.toStaticResources().atCommonLocations()).permitAll() 

Si utiliza Spring Boots 1.5 y posteriores, no necesita permitir estas ubicaciones (estáticas / públicas / webjars, etc.) explícitamente.

Aquí está la nota oficial, ¿qué ha cambiado en el nuevo marco de seguridad en cuanto a las versiones anteriores de sí mismo:

Cambios de seguridad en Spring Boot 2.0 M4

Espero que esto ayude a alguien. ¡Gracias! ¡Que tengas un buen día!

Tuve el mismo problema con mi aplicación de arranque de spring, así que pensé que sería bueno compartir con ustedes mi solución. Simplemente configuro los antMatchers para adaptarlos a un tipo específico de filetes. En mi caso, eso fue solo js filles y js.map . Aquí hay un código:

  @Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() .antMatchers("/index.html", "/", "/home", "/login","/favicon.ico","/*.js","/*.js.map").permitAll() .anyRequest().authenticated().and().csrf().disable(); } } 

Qué es interesante. Descubrí que la ruta de recursos como “resources / myStyle.css” en antMatcher no me funcionaba en absoluto. Si tienes una carpeta dentro de tu carpeta de resoruces, simplemente agrégala a antMatcher como “/myFolder/myFille.js”* y debería funcionar bien.