Security Top

I just announced the new Learn Spring Security course, including the full material focused on the new OAuth2 stack in Spring Security 5:

>> CHECK OUT THE COURSE

1. Overview

It's common for websites to keep their users from visiting the login when they are already logged in. A common way to do that is to redirect the user to another page, usually the starting point of the application after logging in.

In this tutorial, we'll explore multiple ways to implement this solution using Spring Security.

Also, to learn more about how we can quickly implement a login, we can start with this article.

2. Authentication Verification

First, we'll need a method to verify the authentication.

In other words, we'll need to get the authentication details from the SecurityContext and verify if the user is logged in:

private boolean isAuthenticated() {
    Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
    if (authentication == null || AnonymousAuthenticationToken.class.
      isAssignableFrom(authentication.getClass())) {
        return false;
    }
    return authentication.isAuthenticated();
}

We'll use this in all the following components that are responsible for the redirection.

3. Redirecting from the Login Controller

The simplest way to achieve our goal is to define an endpoint for the login page in a controller.

We'll also need to return a specific page if the user is authenticated and the login page otherwise:

@GetMapping("/loginUser")
public String getUserLoginPage() {
    if (isAuthenticated()) {
        return "redirect:userMainPage";
    }
    return "loginUser";
}

4. Using an Interceptor

Another way to redirect users is through an interceptor on the URI of the login page.

The interceptor will intercept the request before it arrives at the controller. Therefore, we can decide based on the authentication if we let it go further or we block it and return a redirect response.

If the user is authenticated, we'll need to modify two things in the response:

  • Set the status code to HttpStatus.SC_TEMPORARY_REDIRECT
  • Add the Location header with the redirect URL

And finally, we'll interrupt the execution chain by returning false:

public class LoginPageInterceptor extends HandlerInterceptorAdapter {
    UrlPathHelper urlPathHelper = new UrlPathHelper();
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        if ("/loginUser".equals(urlPathHelper.getLookupPathForRequest(request)) && isAuthenticated()) {
            String encodedRedirectURL = response.encodeRedirectURL(
              request.getContextPath() + "/userMainPage");
            response.setStatus(HttpStatus.SC_TEMPORARY_REDIRECT);
            response.setHeader("Location", encodedRedirectURL);

            return false;
        } else {
            return true;
        }
    }

    // isAuthenticated method 
}

We'll also need to add the interceptor to the Spring MVC lifecycle:

@Configuration
public class LoginRedirectMvcConfig implements WebMvcConfigurer {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new LoginPageInterceptor());
    }
}

We could use Spring's XML Schema-based configuration to achieve the same:

<mvc:interceptors>
    <mvc:interceptor>
        <mvc:mapping path="/loginUser"/>
        <bean class="com.baeldung.loginredirect.LoginPageInterceptor"/>
    </mvc:interceptor>
</mvc:interceptors>

5. Using a Filter

Similarly, we can implement a Spring filter.

The filter can be directly applied to the SecurityContext using Spring Security's filter chain. Thus, it can intercept the request right after the authentication is created.

Let's extend the GenericFilterBean, override the doFilter method, and verify the authentication:

public class LoginPageFilter extends GenericFilterBean {

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
      throws IOException, ServletException {
        HttpServletRequest servletRequest = (HttpServletRequest) request;
        HttpServletResponse servletResponse = (HttpServletResponse) response;

        if (isAuthenticated() && "/loginUser".equals(servletRequest.getRequestURI())) {

            String encodedRedirectURL = ((HttpServletResponse) response).encodeRedirectURL(
              servletRequest.getContextPath() + "/userMainPage");

            servletResponse.setStatus(HttpStatus.SC_TEMPORARY_REDIRECT);
            servletResponse.setHeader("Location", encodedRedirectURL);
        }

        chain.doFilter(servletRequest, servletResponse);
    }
    // isAuthenticated method 
}

We'll need to add the filter after the UsernamePasswordAuthenticationFilter in the filter chain.

Moreover, we will need to authorize the request for the login page URI to enable the filter chain for it:

@Configuration
@EnableWebSecurity
public class LoginRedirectSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
          .addFilterAfter(new LoginPageFilter(), UsernamePasswordAuthenticationFilter.class)
          .authorizeRequests().antMatchers("/loginUser").permitAll()
           
        // Other security configuration
    }
}

Finally, if we choose to use XML configuration, we can define the bean for the filter, and add it to the filter chain in the security HTTP tag:

<beans:bean id="loginPageFilter" class="com.baeldung.loginredirect.LoginPageFilter"/>

<security:http pattern="/**" use-expressions="true" auto-config="true">
    <security:intercept-url pattern="/loginUser" access="permitAll"/>
    <security:custom-filter after="BASIC_AUTH_FILTER" ref="loginPageFilter"/>
</security:http>

A quick tutorial on how to create a custom filter for Spring Security can be found here.

6. Conclusion

In this tutorial, we've explored multiple ways how to redirect already logged in users from the login page using Spring Security.

As always, the complete source code used in this tutorial is available over on GitHub.

Another tutorial that might be of interest is Redirect to Different Pages after Login with Spring Security, in which we learn how to redirect different types of users to specific pages.

Security bottom

I just announced the new Learn Spring Security course, including the full material focused on the new OAuth2 stack in Spring Security 5:

>> CHECK OUT THE COURSE
guest
0 Comments
Inline Feedbacks
View all comments