更新
按照@Alexandru Clonțea的建议,我检查了提琴手的日志并发现:
无论成功还是失败,实际上都发送了2个请求。两种情况下的第一个请求几乎都是相同的,就像这样:
GET http://myservice.com/handler?param1=something¶m2=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¶m2=somethingelse
Date: Sat, 08 Sep 2018 01:50:16 GMT
Content-Length: 115
<a href="/handler/?param1=something¶m2=somethingelse">Moved Permanently</a>.
我注意到它总是尝试将调用重定向到 / handler /?param1 = something&param2 = somethingelse ,这是由于服务器代码的设置。它实际上按预期工作。区别在于第二个请求。失败案例的第二个请求(这是C#代码) 没有授权标头 ,这就是失败的原因。现在,我的问题是,为什么第二个请求会丢失授权标头?我该如何解决?以下是失败请求的示例:
GET http://myservice.com/handler/?param1=something¶m2=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¶m2=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 ,但是我仍然遇到相同的错误。
我想知道是不是有人曾经看过这个书,或者可以帮忙?我们将不胜感激。
答案 0 :(得分:0)
作为一种解决方法,我可以将请求修改为 http://myservice.com/handler/?param1=something¶m2=somethingelse ,这样就无需重定向。因此,它将得到正确的授权。
但是,仍然没有弄清楚如何通过授权标头发送第二个请求。