HTTP 请求适用于 Postman,但不适用于 C# 代码

Har*_*tes 5 c# http request postman flurl

我想用 C# 做一个简单的 HTTP 请求,但有些东西不起作用,我得到的只是403 Forbidden状态代码。

当我尝试在 Postman 中执行相同的请求时,一切正常。我尝试运行 Fiddler 并查看 Postman 发送的所有标头。我复制粘贴了所有这些,但我仍然收到403 Forbidden了 C# 代码发送的请求。

C# 代码(使用https://fluurl.dev):

public static void Main(string[] args)
{
    FlurlHttp.Configure(settings => {
        settings.HttpClientFactory = new MyClientFactory();
    });

    var url = "https://example.com"
        .AppendPathSegments(new[] { "v1", "oauth", "accesstoken" })
        .SetQueryParam("grant_type", "client_credentials")
        .AllowAnyHttpStatus()
        .WithBasicAuth("username", "password")
        .WithHeaders(new {
            User_Agent = "Something/0.4.0 Dalvik/2.1.0 (Linux; U; Android 5.1.1; SM-G975F Build/NRD90M)",
            X_Secret_Header = "secret_encoded_value",
            accept_encoding = "gzip, deflate",
            Accept = "*/*"
        });

    HttpResponseMessage msg = url.GetAsync().Result;

    Console.WriteLine("StatusCodeString: " + msg.StatusCode.ToString());
    Console.WriteLine();
    Console.WriteLine(msg.Content.ReadAsStringAsync().Result);
}

class MyClientFactory : DefaultHttpClientFactory
{
    public override HttpMessageHandler CreateMessageHandler()
    {
        return new HttpClientHandler
        {
            AllowAutoRedirect = false
        };
    }
}
Run Code Online (Sandbox Code Playgroud)

C# 请求和响应:

Fiddler 中的 CSharp 请求 CSharp响应

邮递员请求和响应:

邮递员标题 邮递员回复 Fiddler 中的邮递员响应

有人可以解释我为什么这不起作用吗?相同的标题,相同的一切。

我用“example.com”替换了 url,因为我不想在这里显示真实的 API URL。

也很抱歉有这么多图片..我不知道如何以其他方式在这里显示问题。

Oce*_*rop 9

对我来说,问题是 C# 中的 TLS 设置。尝试在应用程序的开头或 HTTP 请求代码之前添加此行:

ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
Run Code Online (Sandbox Code Playgroud)

  • 天哪,这对我有用,谢谢!!但为什么将其更改为这个特定协议会有效呢? (4认同)

小智 6

来自 Postman 的右侧应该有一个名为 code 的链接。单击它,然后选择 C# 以获取 Postman 生成的代码。把它贴进去试试。

  • 当您显式设置 Cookie 标头时,Postman 生成的代码在 .NET Framework 应用程序中不起作用。要发送 cookie,您需要在 HttpClient 构造函数中指定处理程序,并使用 `UseCookies = false` 与手动设置 Cookie 标头相结合,或者改用 `CookieContainer`。 (2认同)

Hoc*_*eyJ 5

只是为了帮助任何人搜索 - 导致此类错误的原因可能有多种。

帮助调试此类问题的步骤。

  1. 下载Fiddler(或类似的 Wireshark)来记录网络流量。
  2. 通过邮递员发出工作请求(记录流量)
  3. 通过C#发出失败的请求(记录流量)
  4. 看看这两个请求有什么不同。

就我而言,我在身份验证中得到了引号。这是一个微妙的差异,直到我比较两者时我才意识到

工作电话(200 OK)

使用 fiddler 查看工作调用

呼叫失败(401 未经授权)

使用 fiddler 查看失败的呼叫


elf*_*ico 5

我遇到了类似的问题,这里的所有答案都不起作用。我在 C# 客户端上运行良好403,但在 Postman 中运行良好。几个小时后,按照 @JsAndDotNet 建议使用 fiddler,我发现服务器在没有用户代理的情况下退回了所有请求。

一种确定的方法是检查响应。就我而言,响应应该是 json 格式,但我收到了一个 text/html,这表明服务器将我的请求视为来自浏览器,因此阻止了它。

指定我自己的用户代理(实际上是任何随机字符串)解决了问题


Duc*_*ing 1

下一步是比较来自 C# 代码和 Postman 的原始请求和响应,将它们并排放置并比较差异 - 我向您保证至少会有一个差异。:-)

403是一个授权问题,因此令牌将是第一个嫌疑对象,因为请求的错误结构更有可能引发400“错误请求”错误。

不过,在这种特殊情况下,我已经使用 Flurl 在我的计算机上的 VS2019 中运行了您的代码,它似乎工作正常。它返回一个示例 HTML 页面:

<!doctype html>
<html>
<head>
    <title>Example Domain</title>

    <meta charset="utf-8" />
    <meta http-equiv="Content-type" content="text/html; charset=utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <style type="text/css">
    body {
        background-color: #f0f0f2;
        margin: 0;
        padding: 0;
        font-family: "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;

    }
    div {
        width: 600px;
        margin: 5em auto;
        padding: 50px;
        background-color: #fff;
        border-radius: 1em;
    }
    a:link, a:visited {
        color: #38488f;
        text-decoration: none;
    }
    @media (max-width: 700px) {
        body {
            background-color: #fff;
        }
        div {
            width: auto;
            margin: 0 auto;
            border-radius: 0;
            padding: 1em;
        }
    }
    </style>
</head>

<body>
<div>
    <h1>Example Domain</h1>
    <p>This domain is established to be used for illustrative examples in documents. You may use this
    domain in examples without prior coordination or asking for permission.</p>
    <p><a href="http://www.iana.org/domains/example">More information...</a></p>
</div>
</body>
</html>
Run Code Online (Sandbox Code Playgroud)