Spring Boot部署于Apache2后遭防火墙拦截含"//"的请求问题排查
解决Spring Boot + Apache反向代理下的RequestRejectedException问题
这个问题的核心是Spring Security默认的StrictHttpFirewall会拦截包含"//"的URL,而你的Apache反向代理没有对请求URL中的重复斜杠做处理,直接把带有"//"的请求转发给了后端Spring Boot服务,触发了防火墙拦截。
下面给你两种无需修改防火墙的解决方案,优先推荐第一种(更安全):
方案一:通过Apache配置合并URL中的重复斜杠
在你的Apache虚拟主机配置里,添加Rewrite规则先把URL里的多个斜杠合并成单个,再转发给后端。这样后端收到的请求就不会带有"//"了。
修改后的Apache配置如下:
<VirtualHost *:80> ServerName XXX ProxyPreserveHost on RequestHeader set X-Forwarded-Proto https RequestHeader set X-Forwarded-Port 443 RewriteEngine on # 内部重写:合并URL中的多个斜杠为单个(不触发浏览器跳转) RewriteRule ^(.*)//(.*)$ /$1/$2 [L] # 原有的HTTPS强制跳转规则 RewriteCond %{SERVER_NAME} =XXX RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent] ProxyPass / http://localhost:9001/ ProxyPassReverse / http://localhost:9001/ </VirtualHost>
这个规则会在Apache内部把类似/api//v1/user的请求重写成/api/v1/user,再转发给Spring Boot,从根源上避免触发后端的防火墙拦截。
方案二:调整Spring Security的防火墙规则(仅当方案一不可行时使用)
如果不想修改Apache配置,可以通过自定义Spring Security的StrictHttpFirewall,允许URL中包含双斜杠。注意:这个方案会降低一点安全防护级别,仅在确认业务场景安全的情况下使用。
在你的Spring Boot项目中添加如下配置类:
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.web.firewall.HttpFirewall; import org.springframework.security.web.firewall.StrictHttpFirewall; @Configuration public class SecurityFirewallConfig { @Bean public HttpFirewall allowDoubleSlashHttpFirewall() { StrictHttpFirewall firewall = new StrictHttpFirewall(); // 允许URL中包含编码或未编码的双斜杠 firewall.setAllowUrlEncodedDoubleSlash(true); firewall.setAllowDoubleSlash(true); // 如果还有其他被拦截的特殊字符,也可以在这里添加允许规则 // 比如允许分号:firewall.setAllowSemicolon(true); return firewall; } }
如果你的项目已经有WebSecurityConfigurerAdapter的配置类,还需要在configure方法中指定这个自定义防火墙:
import org.springframework.security.config.annotation.web.builders.WebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; // 假设这是你的WebSecurity配置类 @Configuration public class WebSecurityConfig extends WebSecurityConfigurerAdapter { private final HttpFirewall allowDoubleSlashHttpFirewall; public WebSecurityConfig(HttpFirewall allowDoubleSlashHttpFirewall) { this.allowDoubleSlashHttpFirewall = allowDoubleSlashHttpFirewall; } @Override public void configure(WebSecurity web) throws Exception { web.httpFirewall(allowDoubleSlashHttpFirewall); } // 其他配置... }
这样Spring Security就不会再拦截带有"//"的请求了。
内容的提问来源于stack exchange,提问作者Febell
相关产品推荐
相关产品推荐

