I defined the SecurityFilterChain bean like below

@Bean
    public SecurityFilterChain securityFilterChain (HttpSecurity http) throws Exception {
        // We are disabling CSRF so that our forms don't complain about a CSRF token.
        // Beware that it can create a security vulnerability
        return http.csrf(AbstractHttpConfigurer::disable)
                // Here we are configuring our login form
//              .formLogin(Customizer.withDefaults())
                .formLogin(formLogin -> {
                            formLogin
                                    .loginPage("/login") // Login page will be accessed through this endpoint. We will create a controller method for this.
                                    .loginProcessingUrl("/login-processing") // This endpoint will be mapped internally. This URL will be our Login form post action.
                                    .usernameParameter("username")
                                    .passwordParameter("password")
                                    .permitAll() // We re permitting all for login page
                                    .defaultSuccessUrl("/") // If the login is successful, user will be redirected to this URL.
                                    .failureUrl("/login?error=true"); // If the user fails to login, application will redirect the user to this endpoint
                        }
                )
        .authorizeHttpRequests(authorize ->
                        authorize
                                // We are permitting all static resources to be accessed publicly
                                .requestMatchers("/images/**", "/css/**", "/js/**").permitAll()
                                // We are restricting endpoints for individual roles.
                                // Only users with allowed roles will be able to access individual endpoints.
                                .requestMatchers("/course/add").hasRole("ADMIN")
                                .requestMatchers("/course/show-all").hasAnyRole("ADMIN", "USER")
                                .requestMatchers("/course/edit").hasAnyRole("USER")
                                // Following line denotes that all requests must be authenticated.
                                // Hence, once a request comes to our application, we will check if the user is authenticated or not.
                                .anyRequest().authenticated()
                )

                .logout(logout ->
                        logout
                                .logoutUrl("/logout")
                                .logoutSuccessUrl("/")
                )
                .build();

    }

Unfortunately, this code does not work for custom form login, but works perfectly for form login with default configuration (which is also commented in the code),

Comment From: mainul35

As a result, I am getting the following page. Spring Security Custom Form Login is causing too many redirects and cannot get the login page for Spring Security v6.1.0

Comment From: marcusdacoregio

Hi @mainul35,

can you provide more details about the configuration, like the related code for the custom login page, the /login-processing endpoint etc?

Comment From: mainul35

Hello @marcusdacoregio, Here is my login controller endpoint


@Controller
@RequestMapping("/")
public class RootController {

    @GetMapping("/login")
    public String login(Model model, @RequestParam(name="error", required = false) String error) {
        model.addAttribute("error", error);
        return "auth/login";
    }
}

  • WebMvcConfigurer implementation class

@EnableWebMvc
@Configuration
@ComponentScan(basePackages = { "com.spring5.practice.controllers" })
public class ServletConfig implements WebMvcConfigurer {

    // Configuration to render VIEWS
    public void configureViewResolvers(ViewResolverRegistry registry) {
        registry.jsp("/WEB-INF/views/", ".jsp");
    }

    // Configuration to render STATIC CONTENTS (IMAGE, CSS, JS)
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {

        // Register resource handler for -

        // IMAGES
        registry.addResourceHandler("/images/**").addResourceLocations("/WEB-INF/resources/images/");

        // CSS
        registry.addResourceHandler("/css/**").addResourceLocations("/WEB-INF/resources/css/");

        // JAVASCRIPT
        registry.addResourceHandler("/js/**").addResourceLocations("/WEB-INF/resources/js/");
    }

}


  • Login page location Spring Security Custom Form Login is causing too many redirects and cannot get the login page for Spring Security v6.1.0

  • Login page contents

<%@ page language="java" contentType="text/html; charset=UTF-8"
         pageEncoding="UTF-8" %>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Login</title>
    <link rel="stylesheet"
          href="${pageContext.request.contextPath }/css/bootstrap.min.css">
    <link rel="stylesheet"
          href="${pageContext.request.contextPath }/css/login.css">
    <script type="text/javascript"
            src="${pageContext.request.contextPath }/js/bootstrap.min.js"></script>
    <script type="text/javascript"
            src="${pageContext.request.contextPath }/js/jquery.js"></script>
</head>
<body>
<c:if test="${error == 'true'}">
    <div class="alert alert-danger" role="alert">Wrong username or
        password
    </div>
</c:if>
<div class="sidenav">
    <div class="login-main-text">
        <h2>
            Application<br> Login Page
        </h2>
        <p>Login or register from here to access.</p>
    </div>
</div>
<div class="main">
    <div class="col-md-6 col-sm-12">
        <div class="login-form">
            <form action="${pageContext.request.contextPath }/login-processing"
                  method="POST">
                <div class="form-group">
                    <label>User Name</label> <input type="text" name="username"
                                                    class="form-control" placeholder="User Name">
                </div>
                <div class="form-group">
                    <label>Password</label> <input type="password"
                                                   class="form-control" name="password" placeholder="Password">
                </div>
                <button type="submit" class="btn btn-black">Login</button>
                <button type="submit" class="btn btn-secondary">Register</button>
            </form>
        </div>
    </div>
</div>
</body>
</html>

Please let me know, if you need more information.

Comment From: marcusdacoregio

Can you confirm if it works with Spring Security < 6? It would be nice if you can enable TRACE logs for org.springframework.security and analyze the output.

In addition to that, can you try:

http
  .securityContext(context -> context
    .requireExplicitSave(false)
  )
// ...

Comment From: mainul35

Hello @marcusdacoregio , this project was in Spring 5.2.11 before. I am migrating to Spring 6.x for updating my articles. It was working perfectly. Moreover, just after the release of Spring 6.0, I migrated one of my projects to Spring 6 from Spring 5, and it perfectly works. Here is that project security configuration file link that is currently in Spring 6.0 migrated from 5.x

https://github.com/mainul35/University-QA-Board/blob/migrated/Spring-6.x/src/main/java/com/mainul35/config/security/SecurityConfig.java

  • I will enable TRACE log and let you know the logs ASAP.
  • I just tried the suggeded configuration that you just commented above. It didn't work.

Comment From: mainul35

Hello @marcusdacoregio , after enabling the TRACE log for Spring Security, I found the following line in the log. Spring Security Custom Form Login is causing too many redirects and cannot get the login page for Spring Security v6.1.0

So I set the authorization of my view page location, "/WEB-INF/views/**" in my case to permitAll()


authorize
                                // We are permitting all static resources to be accessed publicly
                                .requestMatchers("/images/**", "/css/**", "/js/**", "/WEB-INF/views/**").permitAll()
                                // We are restricting endpoints for individual roles.
                                // Only users with allowed roles will be able to access individual endpoints.
                                .requestMatchers("/course/add").hasRole("ADMIN")
                                .requestMatchers("/course/show-all").hasAnyRole("ADMIN", "USER")
                                .requestMatchers("/course/edit").hasAnyRole("USER")
                                // Following line denotes that all requests must be authenticated.
                                // Hence, once a request comes to our application, we will check if the user is authenticated or not.
                                .anyRequest().authenticated()

And it worked like a charm!

Thank you for your kind support :)

Comment From: christ774

Good afternoon, I've been trying to solve this error for a long time and I haven't been able to. following your pos it is no longer possible to redirect to a custom login in the latest version of spring

My view is made in html, css and javascript and I also have some images, can you please tell me how I can do it? I also want to ask you if it is more convenient to make a controller, the front connects to it and from there login, it is instead of redirecting the spring security login.

I thank you very much

} /*@Override public void addViewControllers(ViewControllerRegistry viewControllerRegistry){ viewControllerRegistry.addViewController("/login").setViewName("login.html");

}*/
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity) throws Exception {
  httpSecurity.csrf(AbstractHttpConfigurer::disable)// lo desactive por que no me deja trabajar en postman
            .authorizeRequests(authorize ->  authorize
           .requestMatchers("/admin", "/admin/save", "/contenido/save").permitAll()
                    .requestMatchers("src/main/resources/templates").permitAll()
            .anyRequest().authenticated()
          )
          .formLogin(formLogin-> formLogin
                                  .loginPage("/login")
                                  .permitAll()
          );

@Controller public class ControllerLogin {

@RequestMapping(value="/login", method= RequestMethod.GET)
public String login() {
    return "redirect:/login.html";
}

This page isn’t workinglocalhost redirected you too many times. Try clearing your cookies. ERR_TOO_MANY_REDIRECTS

}

Comment From: mainul35

First of all, set /WEB-INF/views/** to permit all, like the code below in your spring security http configuration requestMatchers("/images/**", "/css/**", "/js/**", "/WEB-INF/views/**").permitAll()

Next, in your controller method, return should be only your view name. Replace return "redirect:/login.html"; to return "login";

If your view page is in the correct location, it should work.

Comment From: abhisable

It's not working when we are using below code with mvc.pattern , which is required in latest version. Any suggestions what could be resolution? @Bean public SecurityFilterChain settingUpSecurityFilterChain() throws Exception {

    httpSecurity.authorizeHttpRequests(customizer->{
        customizer.requestMatchers(mvc.pattern("/hello"),mvc.pattern("/helloworld"))
        .authenticated();

        customizer.requestMatchers(mvc.pattern("/bye")).permitAll();
        customizer.requestMatchers(mvc.pattern("/WEB-INF/views/**")).permitAll();
    });

    httpSecurity.formLogin(formLoginCustomizer->{
        formLoginCustomizer.loginPage("/myCustomLogin");
    });

// httpSecurity.formLogin(Customizer.withDefaults()); httpSecurity.httpBasic(Customizer.withDefaults());

    return httpSecurity.build();
}

Comment From: sudheerUzumaki

The configuration httpSecurity.formLogin(formLoginCustomizer -> formLoginCustomizer.loginPage("/myCustomLogin")); instructs Spring Security to redirect unauthorized requests to /myCustomLogin.

To understand why localhost is redirecting excessively, consider this: when an unauthorized request occurs, Spring Security redirects to the login page URL. If this URL requires authentication, it creates a redirect loop back to itself, resulting in the 'localhost redirected too many times' error.

Solution: The solution is to set up HttpSecurity for form login like so: httpSecurity.formLogin(f -> f.loginPage("/loginpage").permitAll());.

If the login page URL is not the URL for the actual page causing the redirection, you should allow "/page.html" without authentication in the request matchers.

HttpSecurity.authorizeHttpRequests(customizer -> customizer.requestMatchers("/page.html").permitAll());

Comment From: SuleymanCommits

The configuration httpSecurity.formLogin(formLoginCustomizer -> formLoginCustomizer.loginPage("/myCustomLogin")); instructs Spring Security to redirect unauthorized requests to /myCustomLogin.

To understand why localhost is redirecting excessively, consider this: when an unauthorized request occurs, Spring Security redirects to the login page URL. If this URL requires authentication, it creates a redirect loop back to itself, resulting in the 'localhost redirected too many times' error.

Solution: The solution is to set up HttpSecurity for form login like so: httpSecurity.formLogin(f -> f.loginPage("/loginpage").permitAll());.

If the login page URL is not the URL for the actual page causing the redirection, you should allow "/page.html" without authentication in the request matchers.

HttpSecurity.authorizeHttpRequests(customizer -> customizer.requestMatchers("/page.html").permitAll());

I've configured form login like that but still experiencing a redirect loop. .formLogin(form -> form.loginPage("/login").permitAll())

Comment From: sudheerUzumaki

The configuration httpSecurity.formLogin(formLoginCustomizer -> formLoginCustomizer.loginPage("/myCustomLogin")); instructs Spring Security to redirect unauthorized requests to /myCustomLogin. To understand why localhost is redirecting excessively, consider this: when an unauthorized request occurs, Spring Security redirects to the login page URL. If this URL requires authentication, it creates a redirect loop back to itself, resulting in the 'localhost redirected too many times' error. Solution: The solution is to set up HttpSecurity for form login like so: httpSecurity.formLogin(f -> f.loginPage("/loginpage").permitAll());. If the login page URL is not the URL for the actual page causing the redirection, you should allow "/page.html" without authentication in the request matchers. HttpSecurity.authorizeHttpRequests(customizer -> customizer.requestMatchers("/page.html").permitAll());

I've configured form login like that but still experiencing a redirect loop. .formLogin(form -> form.loginPage("/login").permitAll())

login is not the page,it returns the page,instead it should be login.jsp or login.html or you can allow it : http..authorizeHttpRequests((authorize) -> authorize .requestMatchers("/login.extension") .permitAll().anyRequest().authenticated())

Comment From: SuleymanCommits

The configuration httpSecurity.formLogin(formLoginCustomizer -> formLoginCustomizer.loginPage("/myCustomLogin")); instructs Spring Security to redirect unauthorized requests to /myCustomLogin. To understand why localhost is redirecting excessively, consider this: when an unauthorized request occurs, Spring Security redirects to the login page URL. If this URL requires authentication, it creates a redirect loop back to itself, resulting in the 'localhost redirected too many times' error. Solution: The solution is to set up HttpSecurity for form login like so: httpSecurity.formLogin(f -> f.loginPage("/loginpage").permitAll());. If the login page URL is not the URL for the actual page causing the redirection, you should allow "/page.html" without authentication in the request matchers. HttpSecurity.authorizeHttpRequests(customizer -> customizer.requestMatchers("/page.html").permitAll());

I've configured form login like that but still experiencing a redirect loop. .formLogin(form -> form.loginPage("/login").permitAll())

login is not the page,it returns the page,instead it should be login.jsp or login.html or you can allow it : http..authorizeHttpRequests((authorize) -> authorize .requestMatchers("/login.extension") .permitAll().anyRequest().authenticated())

doesn't matter, /login is a controller that returns "login" or login.html

Comment From: sudheerUzumaki

The configuration httpSecurity.formLogin(formLoginCustomizer -> formLoginCustomizer.loginPage("/myCustomLogin")); instructs Spring Security to redirect unauthorized requests to /myCustomLogin. To understand why localhost is redirecting excessively, consider this: when an unauthorized request occurs, Spring Security redirects to the login page URL. If this URL requires authentication, it creates a redirect loop back to itself, resulting in the 'localhost redirected too many times' error. Solution: The solution is to set up HttpSecurity for form login like so: httpSecurity.formLogin(f -> f.loginPage("/loginpage").permitAll());. If the login page URL is not the URL for the actual page causing the redirection, you should allow "/page.html" without authentication in the request matchers. HttpSecurity.authorizeHttpRequests(customizer -> customizer.requestMatchers("/page.html").permitAll());

I've configured form login like that but still experiencing a redirect loop. .formLogin(form -> form.loginPage("/login").permitAll())

login is not the page,it returns the page,instead it should be login.jsp or login.html or you can allow it : http..authorizeHttpRequests((authorize) -> authorize .requestMatchers("/login.extension") .permitAll().anyRequest().authenticated())

doesn't matter, /login is a controller that returns "login" or login.html

yes,you are allowing login end point without authentication,but not login.html ,you can also allow it without authentication by : http..authorizeHttpRequests((authorize) -> authorize .requestMatchers("/login.html") .permitAll().anyRequest().authenticated())

Comment From: SuleymanCommits

The configuration httpSecurity.formLogin(formLoginCustomizer -> formLoginCustomizer.loginPage("/myCustomLogin")); instructs Spring Security to redirect unauthorized requests to /myCustomLogin. To understand why localhost is redirecting excessively, consider this: when an unauthorized request occurs, Spring Security redirects to the login page URL. If this URL requires authentication, it creates a redirect loop back to itself, resulting in the 'localhost redirected too many times' error. Solution: The solution is to set up HttpSecurity for form login like so: httpSecurity.formLogin(f -> f.loginPage("/loginpage").permitAll());. If the login page URL is not the URL for the actual page causing the redirection, you should allow "/page.html" without authentication in the request matchers. HttpSecurity.authorizeHttpRequests(customizer -> customizer.requestMatchers("/page.html").permitAll());

I've configured form login like that but still experiencing a redirect loop. .formLogin(form -> form.loginPage("/login").permitAll())

login is not the page,it returns the page,instead it should be login.jsp or login.html or you can allow it : http..authorizeHttpRequests((authorize) -> authorize .requestMatchers("/login.extension") .permitAll().anyRequest().authenticated())

doesn't matter, /login is a controller that returns "login" or login.html

yes,you are allowing login end point without authentication,but not login.html ,you can also allow it without authentication by : http..authorizeHttpRequests((authorize) -> authorize .requestMatchers("/login.html") .permitAll().anyRequest().authenticated())

Securing GET /login 2024-08-12T13:11:23.906+04:00 DEBUG 127703 --- [nio-8080-exec-1] o.s.s.w.a.AnonymousAuthenticationFilter : Set SecurityContextHolder to anonymous SecurityContext 2024-08-12T13:11:23.915+04:00 DEBUG 127703 --- [nio-8080-exec-1] o.s.s.w.a.i.FilterSecurityInterceptor : Authorized filter invocation [GET /login] with attributes [permitAll] 2024-08-12T13:11:23.916+04:00 DEBUG 127703 --- [nio-8080-exec-1] o.s.security.web.FilterChainProxy : Secured GET /login 2024-08-12T13:11:23.949+04:00 DEBUG 127703 --- [nio-8080-exec-1] o.s.security.web.FilterChainProxy : Securing GET /error 2024-08-12T13:11:23.950+04:00 WARN 127703 --- [nio-8080-exec-1] o.s.w.s.h.HandlerMappingIntrospector : Cache miss for ERROR dispatch to '/error' (previous null). Performing MatchableHandlerMapping lookup. This is logged once only at WARN level, and every time at TRACE. 2024-08-12T13:11:23.958+04:00 DEBUG 127703 --- [nio-8080-exec-1] o.s.s.w.a.AnonymousAuthenticationFilter : Set SecurityContextHolder to anonymous SecurityContext 2024-08-12T13:11:23.959+04:00 DEBUG 127703 --- [nio-8080-exec-1] o.s.s.w.a.i.FilterSecurityInterceptor : Authorized filter invocation [GET /error] with attributes [permitAll] 2024-08-12T13:11:23.959+04:00 DEBUG 127703 --- [nio-8080-exec-1] o.s.security.web.FilterChainProxy : Secured GET /error

I don't know why it's redirecting to /error, I've permitted both /login and /login.html and also did .formLogin(form -> form.loginPage("/login").permitAll())

EDIT: Apparently it's because I was visiting the wrong link. My controller class was annotated with @RequestMapping("/user") and then the controller method was annotated with GetMapping("/login) but I was visiting localhost:8080/login instead of localhost:8080/user/login which is why it kept redirecting me to error page. Thanks for the heads up about allowing login.html by the way @sudheerUzumaki

Comment From: wizzy-abhishek

@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
    http
            .csrf(AbstractHttpConfigurer::disable) // Disable CSRF for simplicity, enable in production with proper configuration
            .authorizeHttpRequests(authorize -> authorize
                    .requestMatchers(HttpMethod.GET, "/api/resource").permitAll() // Allow GET requests to /api/resource
                    .requestMatchers(HttpMethod.POST, "/api/resource").hasRole("ADMIN") // Allow POST requests to /api/resource for users with USER role
                    .requestMatchers(HttpMethod.PUT, "/api/resource").hasRole("ADMIN") // Allow PUT requests to /api/resource for users with ADMIN role
                    .requestMatchers(HttpMethod.DELETE, "/api/resource").hasRole("ADMIN") // Allow TO DELETE requests to /api/resource for users with ADMIN role
                    .anyRequest().authenticated()) // All other requests need to be authenticated
            .formLogin(form ->
                    form
                            .loginPage("/login")
                            .permitAll()
                    )
            .httpBasic(Customizer.withDefaults());

    return http.build();
}


<!DOCTYPE html>
Hospital Login Page

Hospital Name

Your expertise , enhanced by our technology

Welcome Back

Forgot Password?

Its a .jsp page

Spring Security Custom Form Login is causing too many redirects and cannot get the login page for Spring Security v6.1.0 spring.mvc.view.suffix=.jsp spring.mvc.view.prefix=/views/

I am stuck kindly help

Comment From: sudheerUzumaki

you should allow "/views/login.jsp" without authentication in the request matchers.

Comment From: koisurunippon

Thanks so much, I had the same problem and your solution above saved me.

Comment From: ranjit485

.requestMatchers("/static/", "/css/", "/js/", "/images/","/WEB-INF/views/**").permitAll() This worked for me