简体   繁体   中英

Spring security default form login page failing when antmatcher defined

I am having an issue with Spring 5 form based authentication. This is only an example at this point as I am trying to isolate the issue I'm having. My plan is to include this configuration in a larger project with multiple configurations. The below code (which can be found anywhere) works as expected:

@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter
{

  @Override
  protected void configure(AuthenticationManagerBuilder auth) throws Exception
  {
    PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
    auth.inMemoryAuthentication()
        .passwordEncoder(passwordEncoder)
        .withUser("user").password(passwordEncoder.encode("password")).roles("USER");
  }

  @Override
  protected void configure(HttpSecurity http) throws Exception
  {
    http
        .authorizeRequests()
        .anyRequest().authenticated()
        .and()
        .formLogin()
        .and().csrf().disable();
  }
}

and following code does not work after adding antmatcher:

@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter
{

  @Override
  protected void configure(AuthenticationManagerBuilder auth) throws Exception
  {
    PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
    auth.inMemoryAuthentication()
        .passwordEncoder(passwordEncoder)
        .withUser("user").password(passwordEncoder.encode("password")).roles("USER");
  }

  @Override
  protected void configure(HttpSecurity http) throws Exception
  {
    http.antMatcher("/test/**")
        .authorizeRequests()
        .anyRequest().authenticated()
        .and()
        .formLogin()
        .and().csrf().disable();
  }
}

Notice that I've only added an antmatcher to this config. I only want the config to apply to /test/**. And, in this case, I'm not doing anything custom with regards to the form login and would like to get Spring default form. Of course in a real application I would not use the default but this is only for example purposes. My first config displays the default internal Spring form correctly when I GET the following URL: http://localhost:8080/webapp/test/anything . And I can authenticate successfully. For the second configuration I get 404 errors when issuing the same URL.

Spring security does in fact try to redirect to: http://localhost:8080/webapp/login however, the url does not exist. I did try the following change:

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.antMatcher("/test/**").authorizeRequests().anyRequest().authenticated()
            .and().formLogin().permitAll().loginPage("/test/login").loginProcessingUrl("/test/login")
            .and().logout().logoutUrl("/test/logout").invalidateHttpSession(true).logoutSuccessUrl("/");
}

This did not work either. I made several attempts, but have not been successful. Is it possible that the default form behavior is disabled when an antmatcher is defined?

This is ideal solution for your requirement

@Override
 protected void configure(HttpSecurity http) throws Exception
 {
    http
        .requestMatchers().antMatchers("/test/**", "/customLoginPage", "/logout").and()
        .authorizeRequests()
        .anyRequest().authenticated()
        .and()
        .formLogin()
        .loginPage("/customLoginPage") //If you don't  configure default is "/login"
        .usernameParameter("userName").passwordParameter("password") //In case of custom form parameters
        .defaultSuccessUrl("/app/user/dashboard") //If you don't  configure default is "/"
        .failureUrl("/login?error=true") //If you don't  configure default is "/login?error"
        .and().csrf().disable();
 }

Let me explain Some cases how spring security deals with

Case 1:

http.authorizeRequests()

is equals to

http.antMatcher("/**").authorizeRequests()

A proxy filter will be defined and url-pattern for that filter will be "/**" . With this type of configuration there will be no problem as it is a wild card. But in some cases we don't want to define wild card "/**" then we should configure requestMatchers correctly otherwise we will end up in lot of unguessable problems.

Case 2:

http.antMatcher("/test/**").authorizeRequests()

Here proxy filter will be added with URL pattern "/test/**" and requests with /login and /logout can't pass through the added filter. To overcome this.requestMatchers() should be used as given below

http
   .requestMatchers().antMatchers("/test/**", "/customLoginPage", "/logout")
   .and().authorizeRequests()

This means filter with filter mapping as given below

<filter-mapping>
    <filter-name>/test/**</filter-name>
    <url-pattern>/customLoginPage</url-pattern>
    <url-pattern>/logout</url-pattern>
</filter-mapping>

You can try out some of basic examples(Working) from my github repository

After many tries, the following is working for me. Only showing the configure method:

@Override
protected void configure(HttpSecurity http) throws Exception
{
    http.antMatcher("/test/**")
        .authorizeRequests()
        .antMatchers("/test/login").permitAll()
        .antMatchers("/test/logout").permitAll()
        .anyRequest().authenticated()
        .and()
        .formLogin()
            .loginPage("/login.jsp").permitAll()
            .loginProcessingUrl("/test/login").permitAll()
            .failureUrl("/login.jsp?error=yes")
        .and()
        .logout().permitAll().logoutUrl("/test/logout").permitAll()
        .and().csrf().disable();
}

I did need to create my own login form (login.jsp), however the processing of the login form (the POST) is handled by Spring default processing. Really, that was the important piece. Another key point to make is that the login form POST needs to point to /webapp/test/login. I suppose that the Spring configuration needs these additional "tips" in order to trigger the default form processing in cases where the antMatcher call must be present.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM