4
votes

La requête HTTP fonctionne dans Postman, mais pas en code C #

Je veux faire une simple requête HTTP en C #, mais quelque chose ne fonctionne pas et tout ce que j'ai est le code d'état 403 Forbidden .

Quand j'essaye de faire la même demande dans Postman, tout fonctionne bien. J'ai essayé d'exécuter Fiddler et de voir tous les en-têtes envoyés par Postman. Je les ai tous copiés, mais j'ai toujours eu 403 Forbidden dans la demande envoyée par code C #.

Code C # (en utilisant 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
        };
    }
}

Demande et réponse C #:

CSharp Request dans FiddlerRéponse de CSharp

Demande et réponse du facteur:

En-têtes de facteurRéponse du facteurRéponse du facteur dans Fiddler

Quelqu'un peut-il m'expliquer pourquoi cela ne fonctionne pas? Mêmes en-têtes, même tout.

J'ai remplacé l'URL par "example.com" car je ne veux pas afficher la véritable URL de l'API ici.

Aussi désolé pour tant d'images ... Je ne sais pas comment montrer le problème ici d'une autre manière.


5 commentaires

Ne publiez pas d'images de texte.


Avez-vous essayé d'utiliser HttpClient C #? Cela produit-il le même résultat?


Y a-t-il une chance que le 403 provienne d'un serveur proxy?


@TobiasTengler Oui, j'ai essayé d'utiliser HttpClient et cela produit le même résultat.


@JohnWu Lorsque j'exécute la requête avec Fiddler, Postman et C # retournent 403. Mais sans Fiddler Postman fonctionne mais C # ne fonctionne pas


5 Réponses :


0
votes

La prochaine étape serait de comparer les demandes et les réponses Raw, de votre code C # et de Postman, de les placer côte à côte et de comparer les différences - je vous assure qu'il y en aurait au moins une. :-)

403 est un problème d'autorisation, donc le jeton serait le premier suspect, car la mauvaise structure de votre requête est plus susceptible de générer une erreur 400 "Mauvaise demande".

Dans ce cas particulier, j'ai exécuté votre code dans VS2019 sur ma machine en utilisant Flurl et cela semble fonctionner correctement. Il renvoie un exemple de page 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>


2 commentaires

J'ai remplacé l'URL réelle par "example.com" car je ne veux pas afficher la véritable API ici


D'accord, donc votre code fonctionne. Maintenant, allez dans l'onglet "Autorisation" du facteur dans l'exemple de travail et vérifiez si le jeton que vous utilisez est le même que celui que vous avez dans votre code VS



0
votes

Ma suggestion serait de récupérer les chaînes de demande brutes du postman et de l'application C # et d'utiliser quelque chose comme https://text-compare.com/ pour rechercher les différences. On suppose qu'il y a une différence extrêmement mineure comme une barre oblique supplémentaire qui est très difficile à remarquer à l'œil nu.


1 commentaires

J'ai comparé les chaînes de requête en utilisant le site que vous avez fourni, mais le résultat dit: "Les deux textes sont identiques"



5
votes

De Postman, il devrait y avoir un lien sur le côté droit appelé code. Cliquez dessus, puis sélectionnez C # pour obtenir le code généré par Postman. Collez-le et essayez-le.


0 commentaires

0
votes

Je connais cet ancien, mais pour obtenir le même code C # que le facteur envoyé, laissez le facteur générer le code pour, mais vous devez d'abord obtenir RestSharp lib à partir de nuget ou de la console PM, tapez ceci:

Install-Package RestRequest -Version 1.2.0

Pas:

1- Appelez votre api de repos du facteur

2- Appuyez sur le bouton code entrez la description de l'image ici 3-Une fenêtre pop-up s'ouvrira, puis choisissez la langue que vous voulez, dans votre cas c'est C # entrez la description de l'image ici


0 commentaires

0
votes

Pour moi, le problème était les paramètres TLS en C #. Essayez d'ajouter cette ligne au début de votre application ou juste avant votre code de requête HTTP:

ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;


0 commentaires