Spring-Boot & Spring-Security Configuration

spring-boot, spring-security

Solution

add this method to SecurityConfig

@Override
public void configure(WebSecurity security){
    security.ignoring().antMatchers("/css/**","/fonts/**","/libs/**"");
}

Problem

I am trying to use Spring Security in my Spring-Boot project. My project structure is: ``` /project -/src/main -- /java -- / resources --- /static ---- /css ---- /fonts ---- /libs --- /templates ---- /all html files ``` Here is my gradle settings: ``` apply plugin: 'java' apply plugin: 'groovy' apply plugin: 'idea' apply plugin: 'spring-boot' apply plugin: 'jacoco' apply plugin: 'war' apply plugin: 'maven' project.ext { springBootVersion = '1.0.2.RELEASE' } dependencies { compile("org.springframework.boot:spring-boot-starter-web:$springBootVersion") compile("org.springframework.boot:spring-boot:1.0.1.RELEASE") compile("org.springframework.boot:spring-boot-starter-thymeleaf") compile("org.springframework.boot:spring-boot-starter-data-jpa:$springBootVersion") compile("org.springframework.security:spring-security-web:4.0.0.M1") compile("org.springframework.security:spring-security-config:4.0.0.M1") ... } ``` Each of my html files has this: ``` <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> <meta name="viewport" content="width=device-width, initial-scale=1.0"/> <meta name="description" content=""/> <link href="/css/bootstrap.css" rel="stylesheet"/> <link href="/css/bootstrap.min.css" rel="stylesheet"/> <link href="/css/bootstrap-responsive.css" rel="stylesheet"/> <link href="/css/bootstrap-responsive.min.css" rel="stylesheet"/> <link href="/css/ofac.css" rel="stylesheet"/> <link href="//netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.css" rel="stylesheet"/> <!-- HTML5 shim, for IE6-8 support of HTML5 elements --> <!--[if lt IE 9]> <script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script> <![endif]--> </head> ``` Here is my MVC Config: @Configuration public class MvcConfig extends WebMvcConfigurerAdapter { ``` @Override public void addViewControllers(ViewControllerRegistry registry) { registry.addViewController( "/home" ).setViewName( "index" ); registry.addViewController( "/" ).setViewName( "index" ); registry.addViewController( "/about" ).setViewName( "about" ); registry.addViewController( "/login" ).setViewName( "login" ); registry.addViewController( "/upload" ).setViewName( "upload" ); registry.addViewController( "/status" ).setViewName( "status" ); registry.addViewController( "/search" ).setViewName( "search" ); } @Override public void addInterceptors(InterceptorRegistry registry) { LocaleChangeInterceptor localeChangeInterceptor = new LocaleChangeInterceptor(); localeChangeInterceptor.setParamName( "lang" ); registry.addInterceptor( localeChangeInterceptor ); } @Bean public LocaleResolver localeResolver() { CookieLocaleResolver cookieLocaleResolver = new CookieLocaleResolver(); cookieLocaleResolver.setDefaultLocale( StringUtils.parseLocaleString( "en" ) ); return cookieLocaleResolver; } @Bean public MessageSource messageSource() { ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource(); messageSource.setBasenames( "classpath:messages/messages", "classpath:messages/validation" ); // if true, the key of the message will be displayed if the key is not // found, instead of throwing a NoSuchMessageException messageSource.setUseCodeAsDefaultMessage( true ); messageSource.setDefaultEncoding( "UTF-8" ); // # -1 : never reload, 0 always reload messageSource.setCacheSeconds( 0 ); return messageSource; } ``` Based on various examples I found online, I have the following security configuration: ``` @Configuration @EnableWebMvcSecurity @EnableGlobalMethodSecurity(prePostEnabled = true) public class SecurityConfig extends WebSecurityConfigurerAdapter { @Autowired private DataSource datasource; @Override protected void configure(HttpSecurity http) throws Exception { http .authorizeRequests() .antMatchers( "/resources/**" ).permitAll(); http .formLogin().failureUrl("/login?error") .defaultSuccessUrl("/") .loginPage("/login") .permitAll() .and() .logout().logoutRequestMatcher(new AntPathRequestMatcher("/logout")).logoutSuccessUrl("/login") .permitAll(); http .authorizeRequests().anyRequest().authenticated(); } @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { JdbcUserDetailsManager userDetailsService = new JdbcUserDetailsManager(); userDetailsService.setDataSource( datasource ); PasswordEncoder encoder = new BCryptPasswordEncoder(); auth.userDetailsService( userDetailsService ).passwordEncoder( encoder ); auth.jdbcAuthentication().dataSource( datasource ); if ( !userDetailsService.userExists( "user" ) ) { List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>(); authorities.add( new SimpleGrantedAuthority( "USER" ) ); User userDetails = new User( "user", encoder.encode( "password" ), authorities ); userDetailsService.createUser( userDetails ); } } } ``` When I navigate to `localhost:9001` I am prompted with my login page. I provide the correct credentials and am redirected to the url: `http://localhost:9001/css/ofac.css` the contents of my css file are shown. Before I added the security, the pages would render correctly. Once the login is successful, the css is shown, but if I navigate the root back to "/" then everything behaves as it should. Can anyone see what I am doing wrong here? Update: I removed the following because Spring-boot will handle the /resources/** ``` http .authorizeRequests() .antMatchers( "/resources/**" ).permitAll(); ``` I also changed the redirect for successful login to: ``` .defaultSuccessUrl("/home") ``` because that is also mapped to "/" However, the behavior is the same. One interesting behavior is that when I use Safari, the login will give me "`http://localhost:9001/css/bootstrap.css`" but Firefox will give me "`http://localhost:9001/css/bootstrap-responsive.min.css`" When I inspect the `POST http://localhost:9001/login` with Firebug I get a "302 Found" followed by a `GET http://localhost:9001/css/bootstrap-responsive.min.css` that returns a 200.

Original source