在 SpringBoot 和 SpringSecurity 应用程序中服务静态 Web 资源

我正在尝试开发 SpringBootweb 应用程序,并使用 Springsecurity java 配置来保护它。

在把我的静态网络资源在’Src/main/resources/public’建议 这里是 Spring 博客,我能够得到静态资源。即在浏览器中按 https://localhost/test.html确实服务于 html 内容。

问题

启用 SpringSecurity 之后,访问静态资源 URL 需要身份验证。

我相关的 Spring Security Java 配置如下所示:-

@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
}

如何配置 蚂蚁以允许将静态资源放置在 src/main/resources/public 中?

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

Ignore any request that starts with "/resources/". This is similar to configuring http@security=none when using the XML namespace configuration.

There are a couple of things to be aware of:

  • The Ant matchers match against the request path and not the path of the resource on the filesystem.
  • Resources placed in src/main/resources/public will be served from the root of your application. For example src/main/resources/public/hello.jpg would be served from http://localhost:8080/hello.jpg

This is why your current matcher configuration hasn't permitted access to the static resources. For /resources/** to work, you would have to place the resources in src/main/resources/public/resources and access them at http://localhost:8080/resources/your-resource.

As you're using Spring Boot, you may want to consider using its defaults rather than adding extra configuration. Spring Boot will, by default, permit access to /css/**, /js/**, /images/**, and /**/favicon.ico. You could, for example, have a file named src/main/resources/public/images/hello.jpg and, without adding any extra configuration, it would be accessible at http://localhost:8080/images/hello.jpg without having to log in. You can see this in action in the web method security smoke test where access is permitted to the Bootstrap CSS file without any special configuration.

If you are using webjars. You need to add this in your configure method: http.authorizeRequests().antMatchers("/webjars/**").permitAll();

Make sure this is the first statement. For example:

@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();
}

You will also need to have this in order to have webjars enabled:

@Configuration
public class MvcConfig extends WebMvcConfigurerAdapter {
...
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
}
...
}

Here is the ultimate solution, after 20+ hours of research.

Step 1. Add 'MvcConfig.java' to your project.

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/");
}
}

Step 2. Add configure(WebSecurity web) override to your SecurityConfig class

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

Step 3. Place all static resources in webapp/resources/..

@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);
}
}

This may be an answer (for spring boot 2) and a question at the same time. It seems that in spring boot 2 combined with spring security everything (means every route/antmatcher) is protected by default if you use an individual security mechanism extended from

WebSecurityConfigurerAdapter

If you don´t use an individual security mechanism, everything is as it was?

In older spring boot versions (1.5 and below) as Andy Wilkinson states in his above answer places like public/** or static/** are permitted by default.

So to sum this question/answer up - if you are using spring boot 2 with spring security and have an individual security mechanism you have to exclusivley permit access to static contents placed on any route. Like so:

@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());
}

}

Please mind this line of code, which is new:

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

If you use spring boot 1.5 and below you don´t need to permit these locations (static/public/webjars etc.) explicitly.

Here is the official note, what has changed in the new security framework as to old versions of itself:

Security changes in Spring Boot 2.0 M4

I hope this helps someone. Thank you! Have a nice day!

i had the same issue with my spring boot application, so I thought it will be nice if i will share with you guys my solution. I just simply configure the antMatchers to be suited to specific type of filles. In my case that was only js filles and js.map. Here is a code:

   @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();
}
}

What is interesting. I find out that resources path like "resources/myStyle.css" in antMatcher didnt work for me at all. If you will have folder inside your resoruces folder just add it in antMatcher like "/myFolder/myFille.js"* and it should work just fine.

In the latest Spring Security 6, the WebSecurityConfigurerAdapter is deprecated.

Declare a WebSecurityCustomizer bean instead.

 @Bean
public WebSecurityCustomizer ignoringCustomizer() {
return (web) -> web.ignoring().requestMatchers("...");
}