I am trying to develop Spring Boot web application and securing it using Spring security java configuration.
After placing my static web resources in 'src/main/resources/public' as advised here in Spring blog, I am able to get the static resources. i.e hitting https://localhost/test.html
in browser do serves the html content.
After I enabled Spring Security, hitting the static resource URL requires authentication.
My relevent Spring Security Java config looks like this:-
@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
}
How should I configure antMatchers to permit static resources placed inside src/main/resources/public ?
This question is related to
spring-mvc
spring-security
spring-boot
@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.
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!
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/");
}
...
}
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.
Source: Stackoverflow.com