Affects: \<6.0.13>


org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter doesn't work while ${spring.mvc.servlet.path} property is not '/'. due to DefaultLoginPageGeneratingFilter only process fixed url path: /login.

public DefaultLoginPageGeneratingFilter(UsernamePasswordAuthenticationFilter authFilter) {
        // DEFAULT_LOGIN_PAGE_URL == "/login"
    this.loginPageUrl = DEFAULT_LOGIN_PAGE_URL;
    this.logoutSuccessUrl = DEFAULT_LOGIN_PAGE_URL + "?logout";
    this.failureUrl = DEFAULT_LOGIN_PAGE_URL + "?" + ERROR_PARAMETER_NAME;
    if (authFilter != null) {
        initAuthFilter(authFilter);
    }
}

// ...

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

private void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
        throws IOException, ServletException {
    boolean loginError = isErrorPage(request);
    boolean logoutSuccess = isLogoutSuccess(request);
    if (isLoginUrlRequest(request) || loginError || logoutSuccess) {
                // !!!!!!
                // Never go into here, while ${spring.mvc.servlet.path} property is not '/'
                // Because '/${spring.mvc.servlet.path}/login' not match '/login'
                // !!!!!!
        String loginPageHtml = generateLoginPageHtml(request, loginError, logoutSuccess);
        response.setContentType("text/html;charset=UTF-8");
        response.setContentLength(loginPageHtml.getBytes(StandardCharsets.UTF_8).length);
        response.getWriter().write(loginPageHtml);
        return;
    }
    chain.doFilter(request, response);
}

For example: the codes below would return 404 ('http://localhost:9018/login' page not found) when visit 'http://localhost:9018/bbb/__admin'

## spring config

spring:
  mvc:
    servlet:
      load-on-startup: 1
      # path != '/'
      path: /bbb

management:
  endpoints:
    enabled-by-default: true
    jmx.exposure.exclude: "*"
    # management endpoints base-path
    web.base-path: /__admin
    web.exposure.include: "*"
// Java Configuration

@Bean
SecurityFilterChain filterChain(HttpSecurity http) throws Exception
{
    String endpointsWebBasePath = AppConfigHolder.getManagementEndpointsBasePath();

    if(GeneralHelper.isStrEmpty(endpointsWebBasePath) || endpointsWebBasePath.equals("/"))
        http.authorizeHttpRequests((authorizeHttpRequests) -> authorizeHttpRequests.anyRequest().permitAll());
    else
    {
        // MVC Servlet Path
        String mvcServletPath = AppConfigHolder.getSpringMvcServletPath();
        String prefix = (GeneralHelper.isStrNotEmpty(mvcServletPath) && !mvcServletPath.equals("/")) ? mvcServletPath : "";

        // managementBasePath = "/bbb/__admin/**"
        String managementBasePath = prefix + endpointsWebBasePath + "/**";

        http
        .authorizeHttpRequests((authorizeHttpRequests) -> authorizeHttpRequests
                // '/bbb/__admin/**' require login
            .requestMatchers(AntPathRequestMatcher.antMatcher(managementBasePath)).authenticated()
            .requestMatchers(AntPathRequestMatcher.antMatcher("/**")).permitAll())
        .formLogin(Customizer.withDefaults())
        .httpBasic(Customizer.withDefaults());
    }

    http.csrf((csrf) -> csrf.disable());

    return http.build();
}

Comment From: bclozel

Could you raise this issue against the Spring Security project directly? It looks like this a configuration problem or an issue specific to Spring Security and your report doesn't point to any particular problem in Spring MVC directly. We can reopen this issue if it turns out that the Spring Security team finds a problem on the Spring Framework side.

I can't unfortunately transfer this issue, so I'm closing it. Thanks!