Spring security StrictHttpFirewall未验证标头

ve7v8dk2  于 2023-10-20  发布在  Spring
关注(0)|答案(1)|浏览(194)

我正在尝试添加我的自定义StrictHttpFirewall,以便在标头不匹配我的模式的情况下拒绝请求。
Spring安全配置如下:

@Configuration
@EnableWebSecurity
class SecurityConfig {

    companion object {
        private val HEADER_NAME_PATTERN = "^[a-z1-9_-]{1,512}$".toRegex(RegexOption.IGNORE_CASE)
        private val HEADER_VALUE_BASE_PATTERN = "[\\p{IsAssigned}&&[^\\p{IsControl}]]*".toRegex()
        private val HEADER_VALUE_ERROR_PATTERN = "[<>]".toRegex()
    }

    @Bean
    fun requestRejectedHandler(): RequestRejectedHandler = ErrorResponseRequestRejectedHandler()

    @Bean
    fun httpFirewall(): HttpFirewall {
        val firewall = StrictHttpFirewall()
        val headerNames = { header: String -> HEADER_NAME_PATTERN.matches(header) }
        val headerValues = { value: String ->
            HEADER_VALUE_BASE_PATTERN.containsMatchIn(value).and(
                !HEADER_VALUE_ERROR_PATTERN.containsMatchIn(value)
            )
        }
        firewall.setAllowedHeaderNames(headerNames)
        firewall.setAllowedHeaderValues(headerValues)
        firewall.setAllowedHttpMethods(
            listOf(GET.name(), POST.name(), PUT.name(), PATCH.name(), DELETE.name())
        )
        return firewall
    }

    @Bean
    @Throws(Exception::class)
    fun filterChain(http: HttpSecurity): SecurityFilterChain =
        http
            .authorizeHttpRequests { it.anyRequest().permitAll() }
            .sessionManagement {
                it
                    .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                    .disable()
            }
            .headers {
                it
                    .frameOptions { option -> option.sameOrigin() }
                    .xssProtection(Customizer.withDefaults())
                    .cacheControl { cache -> cache.disable() }
                    .contentSecurityPolicy(Customizer.withDefaults())
            }
            .cors { it.disable() }
            .csrf { it.disable() }
            .requestCache { it.disable() }
            .build()
}

但不幸的是,它不工作,我仍然能够通过头部,是不匹配我的正则表达式。我有一个很长的调试会话,它看起来像是request本身(由mockMVC制作)拥有所有的头,但是spring security并没有检查request本身的头。有趣的提示:它正在验证我在控制器方法参数级别上指定为强制性的头-如@RequestHeader(value =“my-header”,required = true)。会很感激任何帮助。
已尝试:
1.将httpFirewall显式设置为WebSecurity -未成功
1.添加了自定义过滤器来调试头文件,结果头文件名被验证,但这只是因为我显式调用了request.headerNames.toList(),因为请求本身在内部被HttpFirewallRequest实现 Package ,这已经用我实际期望的验证覆盖了方法getHeaders
1.不仅从mockMvc而且从RestTemplate发出请求,并且通过 Postman 发出请求-不成功

b91juud3

b91juud31#

StrictHttpFirewall检查头,但懒惰。另外,您必须注意,StrictHttpFirewall将请求和响应都 Package 到Wrapper中。
这样,StrictHttpFirewall实际上不会拒绝请求,除非在filterChain下面,请求访问黑名单中的一个头。这意味着即使你有一个被列入黑名单的标头,但过滤器链或控制器中没有人试图从该标头读取,你的请求也不会被拒绝,直到它被尝试读取。
在引入此类保护的PR中,讨论了与此类报头检查的性能相关的问题,因为该检查将执行多次。
为了满足您的要求,我认为StrictHttpFirewall无法处理此问题。要急切地拒绝一个请求,你必须写一个过滤器,它位于过滤器链的开始,或者mvc层,检查是否存在这样的头并拒绝它。
在过滤器链中引入请求的一个好处是,FilterChainProxy接受一个RequestReject(ed)Handler,如果你选择抛出它,它将能够处理RequestReject(ed)Exception

相关问题