仅当从代码(c#)调用时返回未授权(401)

时间:2018-09-07 22:58:19

标签: c# authentication dotnet-httpclient http-status-code-401 go-gin

更新

按照@Alexandru Clonțea的建议,我检查了提琴手的日志并发现:

无论成功还是失败,实际上都发送了2个请求。两种情况下的第一个请求几乎都是相同的,就像这样:

    GET http://myservice.com/handler?param1=something&param2=somethingelse HTTP/1.1
    Authorization: Basic xxxxxx
    Accept: application/json, application/xml, text/json, text/x-json, 
    text/javascript, text/xml
    User-Agent: RestSharp/100.0.0.0
    Host: myservice.com
    Accept-Encoding: gzip, deflate
    Connection: Keep-Alive

对它们的响应是相同的,

    HTTP/1.1 301 Moved Permanently
    Content-Type: text/html; charset=utf-8
    Location: /handler/?param1=something&param2=somethingelse
    Date: Sat, 08 Sep 2018 01:50:16 GMT
    Content-Length: 115

    <a href="/handler/?param1=something&param2=somethingelse">Moved Permanently</a>.

我注意到它总是尝试将调用重定向到 / handler /?param1 = something&param2 = somethingelse ,这是由于服务器代码的设置。它实际上按预期工作。区别在于第二个请求。失败案例的第二个请求(这是C#代码) 没有授权标头 ,这就是失败的原因。现在,我的问题是,为什么第二个请求会丢失授权标头?我该如何解决?以下是失败请求的示例:

GET http://myservice.com/handler/?param1=something&param2=somethingelse HTTP/1.1
Accept: application/json, application/xml, text/json, text/x-json, 
text/javascript, text/xml
User-Agent: RestSharp/100.0.0.0
Accept-Encoding: gzip, deflate
Host: myservice.com

背景: 我在服务器上部署了用GO编写的服务。它需要基本身份验证。例如,我可以通过以下请求成功调用它:

GET /handler/? 
param1=something&param2=somethingelse HTTP/1.1
> Host: myservice.com
> Authorization: Basic xxxxxx
> User-Agent: RestClient/5.16.6
> Accept: */*

上面的请求是由rest api客户端工具(例如邮递员)发出的,它工作正常。如果从浏览器中调用它,它也可以正常工作。

问题: 现在,我尝试使用c#代码对相同的服务进行相同的调用,并且具有:

// pass cert validation
ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, sslPolicyErrors) => true;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;

HttpClient client = new HttpClient();
var byteArray = Encoding.ASCII.GetBytes(username + ":" + password);
var auth = new System.Net.Http.Headers.AuthenticationHeaderValue("Basic", Convert.ToBase64String(byteArray));
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, url);
request.Headers.Authorization = auth;

var response = client.SendAsync(request).Result; // don't need async

但是在这种情况下,我会收到未授权(401)的信息。我已经检查了代码发送的实际请求,它的授权标头与上面显示的完全相同(授权:基本xxxxxx ,而xxxxxx与上面的相同)并且相同uri也是如此。实际上,它发送的所有内容都与我使用rest api客户端工具时的外观相同,但只是代码失败。

当我检查服务器端的日志时,当它返回401时,我会看到以下日志:

  

[GIN-debug]重定向请求301:/ handler-> / hanlder /?param1 = something&param2 = somethingelse

但是当调用来自其他api客户端工具(或浏览器)时,我看不到此日志

您可能从日志中知道,服务器端代码正在使用go gin框架。但是,由于在其他情况下它可以正常工作,因此我认为服务器端代码没有问题。

回到C#代码,我尝试将 HttpWebRequest NetworkCredential 一起使用,而不是 HttpClient ,并且我也尝试使用 client.DefaultRequestHeaders.Authorization = auth ,但是我仍然遇到相同的错误。

我想知道是不是有人曾经看过这个书,或者可以帮忙?我们将不胜感激。

1 个答案:

答案 0 :(得分:0)

作为一种解决方法,我可以将请求修改为 http://myservice.com/handler/?param1=something&param2=somethingelse ,这样就无需重定向。因此,它将得到正确的授权。

但是,仍然没有弄清楚如何通过授权标头发送第二个请求。