Spring Security requiresSecure导致Heroku应用无限重定向求助
问题原因与解决方案
无限重定向的核心原因
Heroku采用SSL终止架构:外部用户的HTTPS请求会先经过Heroku路由器处理,路由器将请求转为HTTP后转发给你的Spring Boot应用。而你配置的.requiresChannel(channel -> channel.anyRequest().requiresSecure())会让Spring Security认为收到的HTTP请求是不安全的,强制重定向到HTTPS;但Heroku路由器又会把这个重定向请求再次转为HTTP转发给应用,最终形成无限循环。
解决步骤
你需要让Spring Security识别Heroku传递的X-Forwarded-Proto请求头(这个头会记录用户原始请求的协议是HTTP还是HTTPS),以此来判断是否需要强制HTTPS。
修改后的SecurityFilterChain配置
@Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { return http // 关键:启用转发头处理,让Spring Security识别Heroku的X-Forwarded-Proto等头 .forwardedHeaders() .and() .addFilterBefore(captchaFilter, UsernamePasswordAuthenticationFilter.class) .authorizeHttpRequests( auth -> auth.requestMatchers("/", "/register", "/index.html", "/static/**", "/favicon.ico", "/manifest.json", "**.png").permitAll() .requestMatchers("/api/auth/**").permitAll() .anyRequest().authenticated() ) .formLogin(form -> form.loginProcessingUrl("/perform_login") .loginPage("/") .successHandler((request, response, authentication) -> {}) .failureHandler((request, response, exception) -> response.setStatus(HttpStatus.BAD_REQUEST.value())) ) // 仅当原始协议不是HTTPS时,才强制重定向到HTTPS .requiresChannel(channel -> channel.requestMatchers(request -> !"https".equals(request.getHeader("X-Forwarded-Proto"))) .requiresSecure() ) .csrf(csrf -> csrf.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()) .csrfTokenRequestHandler(new SpaCsrfTokenRequestHandler()) ) .addFilterAfter(new CsrfCookieFilter(), BasicAuthenticationFilter.class) .logout(logout -> logout.logoutUrl("/api/auth/logout") .deleteCookies("JSESSIONID") .logoutSuccessHandler((request, response, authentication) -> {}) ) .build(); }
额外配置(可选,适配Spring Boot版本)
如果你的Spring Boot版本较低,可能需要在application.properties或application.yml中添加转发头策略配置:
server.forward-headers-strategy=native
内容的提问来源于stack exchange,提问作者Evan
相关产品推荐
相关产品推荐

