Spring Security 5中如何让StrictHttpFirewall仅对特定URL允许分号?
仅针对特定URL开放分号允许的解决方案
当然有办法!你不需要全局启用setAllowSemicolon(true)带来的安全风险,我们可以通过自定义路径匹配的HttpFirewall来实现仅对PrimeFaces Media生成的PDF URL开放分号支持。
实现思路
我们创建一个自定义的HttpFirewall实现,内部维护两个防火墙实例:
- 一个是默认的
StrictHttpFirewall(严格禁止分号),用于绝大多数请求 - 另一个是开启了分号允许的
StrictHttpFirewall,仅匹配PrimeFaces的动态PDF资源路径时使用
具体代码实现
1. 自定义路径匹配的HttpFirewall类
import org.springframework.security.web.firewall.FirewalledRequest; import org.springframework.security.web.firewall.HttpFirewall; import org.springframework.security.web.firewall.StrictHttpFirewall; import org.springframework.security.web.firewall.RequestRejectedException; import jakarta.servlet.http.HttpServletRequest; public class PathBasedHttpFirewall implements HttpFirewall { private final HttpFirewall defaultStrictFirewall; private final HttpFirewall semicolonAllowedFirewall; private final String allowedPathPattern; public PathBasedHttpFirewall(String allowedPathPattern) { // 默认严格防火墙,禁用分号 this.defaultStrictFirewall = new StrictHttpFirewall(); // 允许分号的防火墙实例 this.semicolonAllowedFirewall = new StrictHttpFirewall(); ((StrictHttpFirewall) this.semicolonAllowedFirewall).setAllowSemicolon(true); // 传入需要开放分号的URL匹配模式 this.allowedPathPattern = allowedPathPattern; } @Override public FirewalledRequest getFirewalledRequest(HttpServletRequest request) throws RequestRejectedException { String requestUri = request.getRequestURI(); // 检查当前请求是否匹配目标路径模式 if (requestUri.matches(allowedPathPattern)) { return semicolonAllowedFirewall.getFirewalledRequest(request); } // 其他请求使用默认严格防火墙 return defaultStrictFirewall.getFirewalledRequest(request); } @Override public HttpServletRequest getOriginalRequest(HttpServletRequest request) { return ((FirewalledRequest) request).getOriginalRequest(); } }
2. 在Spring Security配置中注册并使用自定义防火墙
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.web.SecurityFilterChain; import org.springframework.security.web.firewall.HttpFirewall; @Configuration public class SecurityConfig { @Bean public HttpFirewall pathBasedHttpFirewall() { // 精准匹配PrimeFaces Media生成的PDF URL模式,可根据实际情况调整正则 String primeFacesMediaPattern = "^/javax.faces.resource/dynamiccontent.properties;/.*\\.pdf$"; return new PathBasedHttpFirewall(primeFacesMediaPattern); } @Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { // 应用自定义的路径匹配防火墙 http.httpFirewall(pathBasedHttpFirewall()); // 此处添加你的其他安全配置(比如权限控制、登录逻辑等) http.authorizeHttpRequests(auth -> auth .anyRequest().authenticated() ); return http.build(); } }
关键注意事项
- 正则精准性:确保你写的正则表达式只匹配PrimeFaces生成的目标URL,避免过于宽泛的模式导致意外开放其他路径的分号支持,引入安全风险。
- 版本适配:如果你的Spring Security版本较低(比如低于5.7),配置方式可能略有不同,但核心思路一致——通过路径判断切换防火墙规则。
内容的提问来源于stack exchange,提问作者prameela 0807
相关产品推荐
相关产品推荐

