简体   繁体   中英

Return Unauthorized (401) only when calling from code (c#)

UPDATE

As @Alexandru Clonțea suggested, I checked the fiddler log and found:

In both success or fail cases, there are actually 2 requests being sent. The first request are mostly the same for both cases, it's something like:

    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

The response for them are the same, which is:

    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>.

I have noticed that it always try to redirect the call to /handler/?param1=something&param2=somethingelse , and that's because of the setup of the server code. it's actually working as expected. The difference is in the second request. The second request of the failure case (which is the c# code) doesn't have the authorization header and that's why it failed. Now, my question will be, why does the second request miss the authorization header? How can I fix it? Below is an example of the failed request:

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

Backgroud: I have a service written in GO deployed on a server. It requires a basic authentication. For example, I can call it successfully with the following request:

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

The request above is made by a rest api client tool (like postman), and it's working fine. It's also working fine if I call it from a browser.

Problem: Now, I try to make the same call to the same service using c# code, and I have it as:

// 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

But in this case, I am getting Unauthorized (401) back. I have checked into the actually request that was sent by the code, it had exactly the same authorization header as the one shows above ( Authorization: Basic xxxxxx , and the xxxxxx is the same as above) and same uri as well. Actually, everything it sent looks the same as when I used the rest api client tool, but it was just failed in code.

when I check the log on the server side, I see the log below when it returns 401:

[GIN-debug] redirecting request 301: /handler --> /hanlder/?param1=something&param2=somethingelse

but I don't see this log when the call is from the rest api client tool (or browser)

As you may know from the log, the server-side code is using the go gin framework. But since it works fine in other cases, I don't think it's a problem with the server-side code.

Back to the C# code, I have tried to use the HttpWebRequest with NetworkCredential instead of the HttpClient , and I also try to use client.DefaultRequestHeaders.Authorization = auth , but I was still getting the same error.

I am wondering if someone has seen this before or could help? It will be really appreciated.

As a workaround, I can modify the request to be http://myservice.com/handler/?param1=something&param2=somethingelse so that no redirection is needed. Thus, it will be correctly authorized.

But still, haven't figure out how to make the second request to be sent with the authorize header yet.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM