Expand Authors Top

If you have a few years of experience in the Java ecosystem and you’d like to share that with the community, have a look at our Contribution Guidelines.

Expanded Audience – Frontegg – Security (partner)
announcement - icon User management is very complex, when implemented properly. No surprise here.

Not having to roll all of that out manually, but instead integrating a mature, fully-fledged solution - yeah, that makes a lot of sense.
That's basically what Frontegg is - User Management for your application. It's focused on making your app scalable, secure and enjoyable for your users.
From signup to authentication, it supports simple scenarios all the way to complex and custom application logic.

Have a look:

>> Elegant User Management, Tailor-made for B2B SaaS

November Discount Launch 2022 – Top
We’re finally running a Black Friday launch. All Courses are 30% off until tomorrow:

>> GET ACCESS NOW

NPI – Frontegg – Security – (partner)
announcement - icon User management is very complex, when implemented properly. No surprise here.

Not having to roll all of that out manually, but instead integrating a mature, fully-fledged solution - yeah, that makes a lot of sense.
That's basically what Frontegg is - User Management for your application. It's focused on making your app scalable, secure and enjoyable for your users.
From signup to authentication, it supports simple scenarios all the way to complex and custom application logic.

Have a look:

>> Elegant User Management, Tailor-made for B2B SaaS

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 implements HandlerInterceptor {
    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 {

    @Bean
    public SecurityFilterChain filterChain(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.

November Discount Launch 2022 – Bottom
We’re finally running a Black Friday launch. All Courses are 30% off until tomorrow:

>> GET ACCESS NOW

Security footer banner
Comments are closed on this article!