@@ -131,3 +131,104 @@ See https://jira.spring.io/browse/SPR-16851[SPR_16851] for an issue requesting t
131
131
132
132
If you must allow any HTTP method (not recommended), you can use `StrictHttpFirewall.setUnsafeAllowAnyHttpMethod(true)`.
133
133
This will disable validation of the HTTP method entirely.
134
+
135
+ `StrictHttpFirewall` also checks header names and values and parameter names.
136
+ It requires that each character have a defined code point and not be a control character.
137
+
138
+ This requirement can be relaxed or adjusted as necessary using the following methods:
139
+
140
+ * `StrictHttpFirewall#setAllowedHeaderNames(Predicate)`
141
+ * `StrictHttpFirewall#setAllowedHeaderValues(Predicate)`
142
+ * `StrictHttpFirewall#setAllowedParameterNames(Predicate)`
143
+
144
+ NOTE: Also, parameter values can be controlled with `setAllowedParameterValues(Predicate)`.
145
+
146
+ For example, to switch off this check, you can wire your `StrictHttpFirewall` with `Predicate` s that always return `true`, like so:
147
+
148
+ .Allow Any Header Name, Header Value, and Parameter Name
149
+ ====
150
+ .Java
151
+ [source,java,role="primary"]
152
+ ----
153
+ @Bean
154
+ public StrictHttpFirewall httpFirewall() {
155
+ StrictHttpFirewall firewall = new StrictHttpFirewall();
156
+ firewall.setAllowedHeaderNames((header) -> true);
157
+ firewall.setAllowedHeaderValues((header) -> true);
158
+ firewall.setAllowedParameterNames((parameter) -> true);
159
+ return firewall;
160
+ }
161
+ ----
162
+
163
+ .Kotlin
164
+ [source,kotlin,role="secondary"]
165
+ ----
166
+ @Bean
167
+ fun httpFirewall(): StrictHttpFirewall {
168
+ val firewall = StrictHttpFirewall()
169
+ firewall.setAllowedHeaderNames { true }
170
+ firewall.setAllowedHeaderValues { true }
171
+ firewall.setAllowedParameterNames { true }
172
+ return firewall
173
+ }
174
+ ----
175
+ ====
176
+
177
+ Or, there might be a specific value that you need to allow.
178
+
179
+ For example, iPhone Xʀ uses a `User-Agent` that includes a character not in the ISO-8859-1 charset.
180
+ Due to this fact, some application servers will parse this value into two separate characters, the latter being an undefined character.
181
+
182
+ You can address this with the `setAllowedHeaderValues` method, as you can see below:
183
+
184
+ .Allow Certain User Agents
185
+ ====
186
+ .Java
187
+ [source,java,role="primary"]
188
+ ----
189
+ @Bean
190
+ public StrictHttpFirewall httpFirewall() {
191
+ StrictHttpFirewall firewall = new StrictHttpFirewall();
192
+ Pattern allowed = Pattern.compile("[\\p{IsAssigned}&&[^\\p{IsControl}]]*");
193
+ Pattern userAgent = ...;
194
+ firewall.setAllowedHeaderValues((header) -> allowed.matcher(header).matches() || userAgent.matcher(header).matches());
195
+ return firewall;
196
+ }
197
+ ----
198
+
199
+ .Kotlin
200
+ [source,kotlin,role="secondary"]
201
+ ----
202
+ @Bean
203
+ fun httpFirewall(): StrictHttpFirewall {
204
+ val firewall = StrictHttpFirewall()
205
+ val allowed = Pattern.compile("[\\p{IsAssigned}&&[^\\p{IsControl}]]*")
206
+ val userAgent = Pattern.compile(...)
207
+ firewall.setAllowedHeaderValues { allowed.matcher(it).matches() || userAgent.matcher(it).matches() }
208
+ return firewall
209
+ }
210
+ ----
211
+ ====
212
+
213
+ In the case of header values, you may instead consider parsing them as UTF-8 at verification time like so:
214
+
215
+ .Parse Headers As UTF-8
216
+ ====
217
+ .Java
218
+ [source,java,role="primary"]
219
+ ----
220
+ firewall.setAllowedHeaderValues((header) -> {
221
+ String parsed = new String(header.getBytes(ISO_8859_1), UTF_8);
222
+ return allowed.matcher(parsed).matches();
223
+ });
224
+ ----
225
+
226
+ .Kotlin
227
+ [source,kotlin,role="secondary"]
228
+ ----
229
+ firewall.setAllowedHeaderValues {
230
+ val parsed = String(header.getBytes(ISO_8859_1), UTF_8)
231
+ return allowed.matcher(parsed).matches()
232
+ }
233
+ ----
234
+ ====
0 commit comments