I am trying to use Spring Security in my Spring-Boot project.
My project structure:
/project -/src/main -- /java -- / resources --- /static ---- /css ---- /fonts ---- /libs --- /templates ---- /all html files
Here are 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 the following:
<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"/> </head>
Here is my MVC Config: @Configuration The 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" );
Based on various examples that I found on the Internet, 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 go to localhost:9001 , I will be offered a login page. I provide the correct credentials and redirect to the URL: http://localhost:9001/css/ofac.css the contents of my css file are displayed. Before adding security, the pages will display correctly. As soon as the login is successful, css will appear, but if I go back to the root back in "/", then everything will behave as it should.
Can anyone see what I'm doing wrong here?
Update : I deleted the following because Spring-boot will handle / resources / **
http .authorizeRequests() .antMatchers( "/resources/**" ).permitAll();
I also changed the redirect for successful login:
.defaultSuccessUrl("/home")
because it also maps 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 check POST http://localhost:9001/login with Firebug, I get "302 Found" and then GET http://localhost:9001/css/bootstrap-responsive.min.css , which returns 200.