HTTP 请求在 Postman 中有效,但在 C# 代码中无效

Posted

技术标签:

【中文标题】HTTP 请求在 Postman 中有效,但在 C# 代码中无效【英文标题】:HTTP Request works in Postman, but not in C# code 【发布时间】:2019-11-11 09:25:24 【问题描述】:

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

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

C#代码(使用https://flurl.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
        ;
    

C# 请求和响应:

邮递员请求和响应:

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

我将 URL 替换为“example.com”,因为我不想在此处显示真实的 API URL。

对于这么多图片也很抱歉。我不知道如何在此处以其他方式显示问题。

【问题讨论】:

不要发布文字图片。 你试过用C#的HttpClient吗?它会产生相同的结果吗? 403 是否有可能来自代理服务器? @TobiasTengler 是的,我尝试使用 HttpClient 并产生相同的结果。 @JohnWu 当我使用 Fiddler 运行请求时,Postman 和 C# 都返回 403。但是没有 Fiddler,Postman 可以工作,但 C# 不能 【参考方案1】:

在 Postman 的右侧应该有一个名为 code 的链接。单击它,然后选择 C# 以获取 Postman 生成的代码。将其粘贴并尝试一下。

【讨论】:

【参考方案2】:

我知道这很老,但要获得与邮递员发送的相同 C# 代码,让邮递员生成代码,但首先您必须从 nuget 或 PM 控制台获取 RestSharp 库,输入:

Install-Package RestRequest -Version 1.2.0

步骤:

1- 从邮递员那里调用你的 rest api

2- 按密码按钮 3-将打开一个弹出窗口,然后选择您想要的任何语言,在您的情况下是 C#

【讨论】:

【参考方案3】:

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

ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;

【讨论】:

天哪,这对我有用,谢谢!!但是为什么将其更改为此特定协议有效?【参考方案4】:

我的建议是从邮递员和 C# 应用程序中检索原始请求字符串,并使用 https://text-compare.com/ 之类的东西来查找差异。猜测是有一些非常小的差异,比如额外的斜线,用普通的眼睛很难注意到。

【讨论】:

我使用您提供的站点比较了请求字符串,但结果显示:“两个文本相同”【参考方案5】:

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

403 是 authorization problem,因此令牌将是第一个嫌疑人,因为您的请求结构错误更有可能引发 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>

【讨论】:

我用“example.com”替换了实际的url,因为我不想在这里显示真正的api 好的,你的代码可以工作了。现在从工作示例转到邮递员“授权”选项卡,检查您使用的令牌是否与您在 VS 代码中的令牌相同【参考方案6】:

以防万一这对任何人都有帮助。我在调用的 api 上遇到了同样的问题,并且有点不知所措,因为邮递员和 Visual Studio 之间的所有内容(包括授权标头)似乎完全相同。但是当我真正仔细查看提琴手时,我注意到在使用邮递员时,被调用的 api 是 https://api.someplace.com/properties/?pagesize=20 而在视觉工作室中我有 https://api.someplace.com/properties?pagesize=20

请注意“属性”和查询字符串之间缺少斜线。 “...properties/?...” 工作正常,“...properties?...” 导致 403。

我认为(如果我在这里错了,显然纠正我)实际发生的情况是,在第一个 http 调用中,缺少斜杠,服务器使用斜杠将 HTTP 301 重定向到 api。当重定向发生时,授权标头没有被携带,这导致了 403 授权错误。

现在我不知道为什么需要此重定向,我构建的任何 api 都允许这两种情况,并且不需要重定向。但最后,我只是将 url 更改为“../properties/?etc...”,问题就消失了。

【讨论】:

以上是关于HTTP 请求在 Postman 中有效,但在 C# 代码中无效的主要内容,如果未能解决你的问题,请参考以下文章

Http POST 在 Postman 中有效,但在 Flutter 中无效

GET 请求在浏览器中有效,但在 POSTMAN 或 SOAPUI 中无效

POST 请求在 Postman 中有效,但在 Python 请求中无效(200 响应机器人检测)

Workday 请求在 SoapUI 中有效,但在 Postman 中无效

简单的 POST 请求在 Postman 中有效,但在浏览器中无效

GET 请求在浏览器中有效,但在使用 Postman 时我得到了未经授权