Search code examples
spring-bootspring-mvcspring-security

Spring Security- This page isn’t working localhost redirected you too many times. when attempting to access localhost:8080 with Spring Security


Hi I am working on a Spring boot web application in which I am using Spring security and for views I am using JSP pages. when trying to access the pages configured with permitall() that is home page and login page I am getting this error on the browser and nothing is printed on the console. so after adding a logger, I got to know that the controller function is getting called repeatedly below is my code and console screenshot for reference can you please let me know what I am doing wrong here?

Application.properties file for JSP pages

server.error.path=/error 
spring.mvc.view.prefix: /WEB-INF/views/
spring.mvc.view.suffix: .jsp

PageController

@Controller
@RequestMapping(value = "/swadeshiBank/v1")
public class PageController {

    public static final Logger logger = LogManager.getLogger(PageController.class);


    private static final String loginPage = "login";


    @GetMapping(value = "/")
    public String homePage(){
        logger.info("Request Came to home :");
        return "home";
    }

    @GetMapping(value = "/login")
    public String getLoginPage(){
        logger.info("Request Came to login :");
        return loginPage;
    }

}

Security Configuration

@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
            .authorizeHttpRequests(authorize -> authorize
                .requestMatchers("/", "/swadeshiBank/v1/", "/swadeshiBank/v1/login").permitAll() // Public pages
                .requestMatchers("/swadeshiBank/v1/account-details").authenticated() // Authenticated users
                .requestMatchers("/swadeshiBank/v1/admin").hasRole("ADMIN") // Admin users
                .requestMatchers("/swadeshiBank/v1/management").hasRole("MANAGER") // Manager users
                .anyRequest().authenticated()
            )
            .formLogin(form -> form
                .loginPage("/swadeshiBank/v1/login")
                .loginProcessingUrl("/swadeshiBank/v1/login") // URL to submit the login form
                .defaultSuccessUrl("/swadeshiBank/v1/account-details", true)
                .permitAll()
            )
            .logout(logout -> logout
                .logoutRequestMatcher(new AntPathRequestMatcher("/swadeshiBank/v1/logout"))
                .logoutSuccessUrl("/swadeshiBank/v1/login?logout")
                .invalidateHttpSession(true)
                .permitAll()
            );

        return http.build();
    }

    @Bean
    public UserDetailsService userDetailsService() {
        InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
        manager.createUser(User.withUsername("user")
                .password("{noop}password")
                .roles("USER")
                .build());
        manager.createUser(User.withUsername("admin")
                .password("{noop}admin")
                .roles("ADMIN")
                .build());
        manager.createUser(User.withUsername("manager")
                .password("{noop}manager")
                .roles("MANAGER")
                .build());
        return manager;
    }
}

Project Structure

Project Structure

Console Screenshot Console Screenshot

Browser Screenshot Browser screenshot

Can you please help me here? additionally, Current behaviour what I noticed when I type

http://localhost:8080/ in browser it takes me to http://localhost:8080/swadeshiBank/v1/login but I want the landing page should be http://localhost:8080/swadeshiBank/v1/ and login page should only appear when I click on login button.


Solution

  • When you set your spring-security logger to DEBUG, you can see that spring tries to access login.jsp as a secured resource, meaning it locks the file behind its security features.

    Since the file-url /WEB-INF/views/login.jsp is not recognized by any request-matchers you defined, it is only allowed for authenticated users, as that is what you set for anyRequest() in your http.authorizeHttpRequests() lambda-function. This still allows the /login url to be accessed without authentication, but the request to the login.jsp file is getting blocked by spring. Whenever spring blocks a request, it redirects the user to the login-page. Since you re-routed the /login url to your custom endpoint, this would loop forever if there weren't a hard limit for the amount of redirects.

    To solve your issue, it should suffice to add the /WEB-INF/views/login.jsp resource-endpoint to your request-matchers that have the permitAll() option, like so:

    
    // Class and stuff above
    
        @Bean
        public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
            http
                .authorizeHttpRequests(authorize -> authorize
                    .requestMatchers("/", "/swadeshiBank/v1/", "/swadeshiBank/v1/login", "/WEB-INF/views/login.jsp").permitAll() // Public pages
                    .requestMatchers("/swadeshiBank/v1/account-details").authenticated() // Authenticated users
                    .requestMatchers("/swadeshiBank/v1/admin").hasRole("ADMIN") // Admin users
                    .requestMatchers("/swadeshiBank/v1/management").hasRole("MANAGER") // Manager users
                    .anyRequest().authenticated()
                )
    
    // Your form-login-settings
    
    // Your logout-settings
    
            return http.build();
        }
    
    // Stuff below the method