简体   繁体   中英

How can I redirect users after logging in to the home page and throw out a 200 instead of a 302 with Spring Security?

I'm currently experimenting with Spring Boot and trying to create a simple web app with a REST backend. I'm authenticating users with Spring Security, using the following configurations:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.csrf.CookieCsrfTokenRepository;

@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
public class ApplicationSecurityConfig extends WebSecurityConfigurerAdapter{
    private final PasswordEncoder passwordEncoder;
    private final UserDetailsServiceImpl dbUserDetailService;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                // Generate a CSRF token (for some reason it doesn't do it automatically)
                .csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
                .and()

                // Now we authorize requests based on our rules
                .authorizeRequests()
                // Anyone is authorized for a request to "/"
                .antMatchers("/", "/registration").permitAll()
                // Only admin roles can request to POST "/registration"
                .antMatchers("/success").hasRole("USER")
                .anyRequest()
                .authenticated()
                .and()
                .formLogin()
                .loginPage("/")
                .permitAll()
                .and().csrf().disable()
                .logout()
                .logoutUrl("/logout")
                .clearAuthentication(true)
                .invalidateHttpSession(true)
                .deleteCookies("JSESSIONID");
    }

    @Bean
    public AuthenticationProvider daoAuthenticationProvider(){
        DaoAuthenticationProvider provider =
                new DaoAuthenticationProvider();
        provider.setPasswordEncoder(passwordEncoder);
        provider.setUserDetailsService(this.dbUserDetailService);
        return provider;
    }
}

Currently, when the user successfully logins, instead of a 200 HTTP status code, it will send a 302. Likewise, when the user unsuccessfully does so (bad credentials), instead of a 401, it will send a 302. This behavior makes sense to me, so I think my approach to my web app is wrong.

What I'm trying to accomplish is that a successful login attempt results in a 200 status code and redirects the user to the home page. A bad login attempt results in a 401 status code and the page is the same except it'll have a message indicating that the attempt failed. How can I accomplish this?

If you want to redirect, then you should send 302 instead of 200. This will give the browser indication to redirect to the new url.

so you just need to set a redirectSuccessUrl which in this case would be defaultSuccessUrl in the configure method.

Configure Method

http
  .authorizeRequests()
  .antMatchers("/login*")
  .permitAll()
  .anyRequest()
  .authenticated()
  .and()
  .formLogin().defaultSuccessUrl("/homepage.html", true);

For Authentication Failure you can use a failure handler like in this site https://www.baeldung.com/spring-security-custom-authentication-failure-handler

This is for normal spring based web applications.

if you are using some frontend framework like Angular, then you should override the Success and Failure handler and add it configure method

public class AppAuthenticationSuccessHandler extends SimpleUrlAuthenticationSuccessHandler{
    protected void handle(HttpServletRequest request, HttpServletResponse response,
            Authentication authentication) throws IOException, ServletException {
    }

}

@Bean
public AuthenticationSuccessHandler appAuthenticationSuccessHandler(){
     return new AppAuthenticationSuccessHandler();
}


http
  .authorizeRequests()
  .antMatchers("/login*")
  .permitAll()
  .anyRequest()
  .authenticated()
  .and()
  .formLogin()
  .successHandler(new appAuthenticationSuccessHandler())
  .failureHandler(new AppAuthenticationFailureHandler());

In the frontend framework based on the response code you get from spring which is either 200 or 401, you should do the redirection to homepage or show an error message

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