Home > Software engineering >  Spring Security - Redirect to entered url after success login
Spring Security - Redirect to entered url after success login

Time:11-15

I have been working on Spring Security I use a role based authentication. If the user is admin he will be directed to admindashboard and user will be redirected to his respective dashboard where they share a common login portal.

If a person enters a url of the admin/user dashboard before login it asks the person to login but doesn't redirect to entered url. Instead throws an error "cannot call sendRedirect".

My code for security configuration file

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Autowired;
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.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
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.core.Authentication;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
import org.springframework.web.util.UrlPathHelper;

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private UserDetailsService userDetailsService;
    @Autowired private LoginSuccessHandler loginSuccessHandler;
    @Bean
    AuthenticationProvider authenticationProvider() {
        DaoAuthenticationProvider provider=new DaoAuthenticationProvider();
        provider.setUserDetailsService(userDetailsService);
        provider.setPasswordEncoder(new BCryptPasswordEncoder());
        return provider;
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests().antMatchers("/").permitAll()
        .antMatchers("/userhome").hasAuthority("USER").
        antMatchers("/adminhome").hasAuthority("ADMIN")
        .antMatchers("/register").permitAll()
        .and().formLogin().loginPage("/login")
        .successHandler(loginSuccessHandler)
        .permitAll().and().logout().logoutSuccessHandler(new LogoutSuccessHandler() {
            @Override
            public void onLogoutSuccess(HttpServletRequest request,HttpServletResponse response,Authentication authentication) throws   IOException,ServletException{
                System.out.println("The User " authentication.getName()   " has logged out");
                UrlPathHelper helper=new UrlPathHelper();
                String context=helper.getContextPath(request);
                response.sendRedirect(context "/home");
            }
        }).permitAll();
        http.csrf().disable();
        
    }
    
    @Bean
    public BCryptPasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    
}

My Login Successful handler

package strictly.cinema.config;

import java.io.IOException;
import java.util.Collection;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;
import org.springframework.stereotype.Component;

import strictly.cinema.service.CustomUserDetails;

@Component
public class LoginSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler{
    @Override
     public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
                Authentication authentication) throws ServletException, IOException {
     
            CustomUserDetails userDetails = (CustomUserDetails) authentication.getPrincipal();
            Collection<? extends GrantedAuthority> authorities =userDetails.getAuthorities();
            authorities.forEach(auth->System.out.println(auth.getAuthority()));
            String redirectURL=request.getContextPath();
            if(userDetails.hasRole("USER"))
                redirectURL ="/userhome";
            else if(userDetails.hasRole("ADMIN"))
                redirectURL ="/adminhome";
            
            response.sendRedirect(redirectURL);
            super.onAuthenticationSuccess(request, response, authentication); 
        }
}

Overriden the logout handler in the security handler itself. Need help to store the entered URL once the user is authenticated and eligible to access the URL he should be redirected to the URL after the login

CodePudding user response:

Instead of using successHandler, you could redirect him to a success endpoint as follow :

.defaultSuccessUrl("/loginSuccess")

And the new endpoint will redirect him to "/userhome" or "/adminhome" based on his role. (Below was not tested)

Success endpoint :

@GetMapping("/loginSuccess")
public void getLoginInfo(
        @AuthenticationPrincipal UserDetails authentication,
        HttpServletResponse response) throws IOException {
    if (authentication.getAuthorities()
            .contains(new SimpleGrantedAuthority("ADMIN"))) {
        response.sendRedirect("/adminhome");
    } else {
        response.sendRedirect("/userhome");
    }
}
  • Related