You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何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触发内容检测。

针对性解决方法

  1. 统一Content-Type格式:避免自动添加charset后缀,直接用StringContent构造请求体:
var json = JsonConvert.SerializeObject(new { PatientCode = "123456", Password = "123456" });
var content = new StringContent(json, Encoding.UTF8, "application/json");
  1. 禁用Expect: 100-continue头:在HttpClientHandler中关闭该默认行为:
httpClientHandler.Expect100Continue = false;
  1. 格式化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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 16:00:59