Spring Boot控制器未被调用

前端开发 2026-07-10

我们正在升级到Spring Boot 3.5.5,因此有些代码是历史遗留的。

我们有一个中心门户应用,用户可以在其中登录。它根据不同用户提供不同的登录方式。Spring Boot框架(3.5.5)的所有通用配置都放在一个公用共享库中,与其他应用保持一致(那些应用运行良好)。

问题:
门户应用启动正常。日志中没有记录任何错误或异常。

当在浏览器中打开应用时按预期会跳转到 /auth/login,但页面并未显示。用于返回登录页的控制器根本没有被调用。

@Configuration
@EnableWebSecurity()
@Profile(value = { Constants.AUTH_STRATEGY_CUSTOM })
public class CustomStrategyConfiguration {

    private static final Logger logger = LoggerFactory.getLogger(CustomStrategyConfiguration.class);

    public static final String AUTHENTICATION_FAILURE_URL = "/auth/login";
    public static final String AUTHENTICATION_SUCCESS_URL = "/dashboard/";

    @Autowired
    private MultiProviderAuthenticationManager authenticationManager;

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {

        HttpSessionRequestCache requestCache = new HttpSessionRequestCache();
        requestCache.setMatchingRequestParameterName(null);

        http
        //.securityMatcher("/**")   
        .authenticationManager(authenticationManager)
        .authorizeHttpRequests((authorizeHttpRequests) 
                -> authorizeHttpRequests
                    .requestMatchers("/resources/**","/static/**", "/img/**", "/bootstrap/**", "/uikit/**", "/**.js", "/**.css").permitAll()
                    .requestMatchers("/auth/login", "/auth/login/","/auth/login/**", "/login","/auth/**","/auth/login/verify","/auth/login?error", "/services/uiStatus/**").permitAll()
                    .requestMatchers("/profile/password/forgotPassword","/profile/password/forgotPassword/**","/profile/password/forgotPassword.do","/profile/password/resetForgottenPassword/**","/profile/password/resetForgottenPassword.do").permitAll()
                    .requestMatchers("/META-INF/MANIFEST.MF","/META-INF/**").denyAll()
                    .requestMatchers("/oauth/authorize").authenticated()

                    .anyRequest().authenticated()           
                )
        .sessionManagement((sessionsManagement) -> sessionsManagement.sessionFixation().migrateSession().maximumSessions(1))
        .requestCache((rc) -> rc.requestCache(requestCache))
        .formLogin((formLogin) 
                -> formLogin
                .loginPage("/auth/login")
                .loginProcessingUrl("/auth/login/verify")
                .defaultSuccessUrl(AUTHENTICATION_SUCCESS_URL, true)
                .failureUrl(AUTHENTICATION_FAILURE_URL).permitAll()
                .usernameParameter("usernamme")
                .passwordParameter("password"))
        .exceptionHandling((e) -> e.authenticationEntryPoint(new LoginUrlAuthenticationEntryPoint("/auth/login")))
        .logout((logout) 
                -> logout
                .logoutUrl("/auth/logout")
                .logoutSuccessUrl("/loggedOut")
                .addLogoutHandler(logoutAuditListener()))

        .sessionManagement((sessionManagement) 
                -> sessionManagement
                .sessionFixation((sfc) -> sfc.migrateSession())
                .maximumSessions(1)
                .sessionRegistry(sessionRegistry()))
        .headers((headers) 
                -> headers
                .xssProtection((xss) -> xss.disable())
                .frameOptions((frameOptions) -> frameOptions.disable())
                .contentSecurityPolicy(csp -> csp.policyDirectives(
                        "default-src 'self'; " +
                        "script-src 'self' 'unsafe-inline' 'unsafe-eval'; " +
                        "style-src 'self' 'unsafe-inline'; " +
                        "object-src 'none'; " +
                        "img-src 'self'; " +
                        "frame-ancestors 'self';")
                ))
        .csrf((csrf) -> csrf.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()))
        //.oauth2ResourceServer(oauth2 -> oauth2.opaqueToken(otc -> otc.introspectionUri("/login").introspectionClientCredentials("test", "test")))
        .addFilterAfter(authenticationTokenParsingFilter(), AbstractPreAuthenticatedProcessingFilter.class)
        ;

        return http.build();
    }


    @Bean
    public SessionRegistry sessionRegistry() {
        return new SessionRegistryImpl();
    }



    @Bean
    public LogoutAuditListener logoutAuditListener() {
        return new LogoutAuditListener();
    }

}
@Component
public class MultiProviderAuthenticationManager implements AuthenticationManager{

    @Autowired
    private AuthenticationMethodRegistry authenticationMethodRegistry;

    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
         for (AuthenticationMethod method : authenticationMethodRegistry.getAuthenticationMethods()) {
             if(method == null || method.getAuthenticationProvider() == null) {
                 continue;
             }
             AuthenticationProvider provider = method.getAuthenticationProvider();
             if (provider.supports(authentication.getClass())) {
                 Authentication result = provider.authenticate(authentication);
                 if (result != null) {
                     return result;
                 }
             }
         }
        return null;
    }

}
@Component
public class AuthenticationTokenParsingFilter extends AbstractAuthenticationProcessingFilter {

    @Autowired
    private AuthenticationMethodRegistry methodRegistry;

    @Autowired
    private AuthenticationEventPublisher authenticationEventPublisher;


    public AuthenticationTokenParsingFilter(AuthenticationManager authenticationManager) {
        super("/auth/login/verify");
        setAuthenticationSuccessHandler(new SimpleUrlAuthenticationSuccessHandler(CustomStrategyConfiguration.AUTHENTICATION_SUCCESS_URL));
        setAuthenticationManager(authenticationManager);

        SimpleUrlAuthenticationFailureHandler handler = new SimpleUrlAuthenticationFailureHandler();
        handler.setDefaultFailureUrl(CustomStrategyConfiguration.AUTHENTICATION_FAILURE_URL);
    }

    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException, IOException, ServletException {
        Collection<AuthenticationMethod> methods = methodRegistry.getAuthenticationMethods();
        Authentication auth = null;
        try {
            for (AuthenticationMethod method : methods) {
                if (!method.isEnabledGlobal()) {
                    // skip evaluation if it is disabled per configuration
                    continue;
                }
                AbstractAuthenticationProcessingFilter filter = method.getFilter();
                if (filter != null) {
                    auth = filter.attemptAuthentication(request, response);
                    if (auth != null) {
                        // publish authentication event
                        authenticationEventPublisher.publishAuthenticationSuccess(auth);
                        break;
                    }
                }
            }
        } catch (AuthenticationException ex) {
            authenticationEventPublisher.publishAuthenticationFailure(ex, auth);
            throw ex;
        }

        return auth;
    }

}
@SpringBootApplication(exclude = { JerseyServerMetricsAutoConfiguration.class })
@EnableScheduling
@ComponentScan(value = "my.company")
@EnableJpaRepositories(value = "my.company", repositoryBaseClass = BasemRepositoryImpl.class)
@EnableMethodSecurity(proxyTargetClass = true)
@Configuration()
public class PlatformApplication extends SpringBootServletInitializer {
....

@Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
        builder.logStartupInfo(true);
        List<String> profiles = getActiveProfiles();
        profiles.add(PlatformApplication.SPRING_PROFILE_RUNTIME);
        profiles.add(getAuthenticationStrategyProfile());
        String[] profilesArray = new String[profiles.size()];
        profilesArray = profiles.toArray(profilesArray);
        builder.profiles(profilesArray);

        builder.listeners(new CustomApplicationListener());

        return builder;
    }

}

解决方案

// REMOVE THIS
.exceptionHandling(e ->
    e.authenticationEntryPoint(
        new LoginUrlAuthenticationEntryPoint("/auth/login")
    )
)

When a request is unauthenticated or the user provides invalid credentials, Spring Security dispatches the request to the configured AuthenticationEntryPoint (/auth/login). When a user initially accesses the web application, no authentication is present in the security context, so the framework redirects the request to the authentication entry point. However, since authentication is still missing when /auth/login itself is requested, the same condition occurs again, causing the AuthenticationEntryPoint to be invoked repeatedly. This results in an infinite redirect loop, preventing the login controller from ever being reached.

站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章