为何ModSecurity拦截HttpClient的POST请求,却不拦截RestSharp与Postman的?
问题描述
我有一个由本地服务商托管的REST API,安装了Plesk面板且默认开启ModSecurity。GET请求一切正常,但POST请求出现异常:使用.NET内置HttpClient发送POST请求时,会被ModSecurity以HTTP 502.3错误拦截,对应代码如下:
var content = JsonContent.Create(new { PatientCode = "123456", Password = "123456" // auth data }); content.Headers.ContentType = new MediaTypeHeaderValue("application/json"); using (var httpClientHandler = new HttpClientHandler()) { httpClientHandler.ServerCertificateCustomValidationCallback = (message, cert, chain, errors) => { return true; }; // mock for invalid SSL using (var client = new HttpClient(httpClientHandler)) { var response = await client.PostAsync("https://example.com/post", content); try { var responseString = await response.Content.ReadAsStringAsync(); var result = JsonConvert.DeserializeObject<AuthenticationResponse>(responseString); } catch (Exception ex) { Console.WriteLine(ex); } } }
而使用RestSharp的代码却能正常获取响应:
var options = new RestClientOptions("https://example.com/post") { RemoteCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) => true // mock for invalid SSL }; var client = new RestClient(options); var request = new RestRequest() .AddJsonBody(new { PatientCode = "123456", Password = "123456" // auth data }); request.AddHeader("Content-Type", "application/json"); var response = await client.PostAsync<AuthenticationResponse>(request);
此外,用Postman发送相同请求也能正常工作,Postman生成的HTTP请求如下:
POST /post HTTP/1.1 Host: example.com Content-Type: application/json Content-Length: 58 { "PatientCode":"123456", "Password":"123456" }
疑问:为何ModSecurity会拦截HttpClient的POST请求,却不拦截RestSharp与Postman的请求?
原因分析与解决方案
核心差异点
ModSecurity的拦截通常源于请求细节的差异,以下是可能的触发原因:
- Content-Type头格式不同:HttpClient的
JsonContent.Create默认会自动在Content-Type中追加; charset=utf-8,最终头内容为application/json; charset=utf-8,而RestSharp和Postman设置的是纯application/json。部分ModSecurity规则会对带字符集后缀的Content-Type误判为异常请求。 - 默认携带额外请求头:HttpClient默认会发送
Expect: 100-continue头,这个头可能触发了ModSecurity的可疑请求检测规则,而RestSharp和Postman默认不会添加该头。 - JSON序列化格式差异:HttpClient的JsonContent默认生成紧凑格式的JSON(无换行缩进),而Postman、RestSharp发送的是带格式化的JSON,部分ModSecurity规则会对紧凑格式的JSON触发内容检测。
针对性解决方法
- 统一Content-Type格式:避免自动添加charset后缀,直接用
StringContent构造请求体:
var json = JsonConvert.SerializeObject(new { PatientCode = "123456", Password = "123456" }); var content = new StringContent(json, Encoding.UTF8, "application/json");
- 禁用Expect: 100-continue头:在HttpClientHandler中关闭该默认行为:
httpClientHandler.Expect100Continue = false;
- 格式化JSON请求体:将JSON序列化为带缩进的格式,与Postman保持一致:
var json = JsonConvert.SerializeObject(new { PatientCode = "123456", Password = "123456" }, Formatting.Indented); var content = new StringContent(json, Encoding.UTF8, "application/json");
内容的提问来源于stack exchange,提问作者Slepoyi
相关产品推荐
相关产品推荐

