0
votes

I'm using Spring Security 4.0.3 with a custom login form and Spring MVC 4.1.1, running in Glassfish 4.1.

My custom login page is presented correctly when I ask for a secured URL (/app/**). However, when the login form is submitted (POST /j_security_check), this request results in a basic authentication dialog being displayed. It seems that something feels that /j_security_check is a resource which is protected by basic authentication at the Glassfish level, since I get a 401 Unauthorized page from Glassfish when I hit Cancel on the dialog.

Here is my MVC initializer:

public class SpringMvcInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {

    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class[] { MvcConfiguration.class, SecurityConfiguration.class, PersistenceConfiguration.class };
    }

    @Override
    protected Class<?>[] getServletConfigClasses() {
        return null;
    }

    @Override
    protected String[] getServletMappings() {
        return new String[] { "*.html", "/j_security_check" };
    }

}

My MVC Config:

@Configuration
@EnableWebMvc
@ComponentScan(basePackages = {"com.elemenopy.wishlist"})
public class MvcConfiguration extends WebMvcConfigurerAdapter {

    @Bean
    public ViewResolver viewResolver() {
        InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
        viewResolver.setViewClass(JstlView.class);
        viewResolver.setPrefix("/WEB-INF/jsp/");
        viewResolver.setSuffix(".jsp");

        return viewResolver;
    }

     /*
     * Configure ResourceHandlers to serve static resources like CSS/ Javascript etc...
     */
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/static/**").addResourceLocations("/static/");
    }

    @Bean
    public MessageSource messageSource() {
    ResourceBundleMessageSource source = new ResourceBundleMessageSource();
    source.setBasenames("messages", "validationMessages");
    return source;
    }

    @Bean
    @Override
    public Validator getValidator() {
    LocalValidatorFactoryBean factory = new LocalValidatorFactoryBean();
    factory.setValidationMessageSource(messageSource());
    return factory;
    }

    @Bean
    public MessageSourceAccessor messageSourceAccessor() {
    return new MessageSourceAccessor(messageSource());
    }
}

My security config:

@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Autowired
    public void configureGlobalSecurity(AuthenticationManagerBuilder auth) throws Exception {
    auth.inMemoryAuthentication().withUser("[email protected]").password("abc123").roles("USER");
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {

    http
        .authorizeRequests()
        .antMatchers("/static/**", "/*.jsp").permitAll()
        .antMatchers("/").permitAll()
        .antMatchers("/home.html").permitAll()
        .antMatchers("/start.html").permitAll()
        .anyRequest().authenticated()
        .and()
        .formLogin().loginPage("/login.html").permitAll()
        .and()
        .logout().logoutUrl("/logout.html").permitAll();
    }

    @Bean
    public PasswordEncoder getPasswordEncoder() {
    return new BCryptPasswordEncoder();
    }

    @Bean
    public AuthenticationManager authManager() throws Exception {
    return authenticationManagerBean();
    }
}

Any help would be greatly appreciated. Thanks!

1

1 Answers

0
votes

Don't know why I didn't find this while I was searching before, but it turns out with Spring Security 4, your login form post URI has to be consistent with the URI of the login page itself. Not a hardcoded URI like /j_security_check.

spring security 4 custom login page