Возврат неавторизованного (401) только при звонке с кода (C#)
ОБНОВИТЬ
Как подсказал @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= что-то ¶m2= что-то еще, и это из-за настройки кода сервера. это на самом деле работает, как ожидалось. Разница во втором запросе. Второй запрос случая сбоя (который является кодом 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
Backgroud: у меня есть служба, написанная на 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) обратно. Я проверил на самом деле запрос, который был отправлен кодом, у него был точно такой же заголовок авторизации, как показано выше (Авторизация: Basic xxxxxx, и xxxxxx такой же, как указано выше), а также тот же URI. На самом деле все, что он отправлял, выглядит так же, как когда я использовал клиентский инструмент rest api, но в коде это просто не получилось.
когда я проверяю журнал на стороне сервера, я вижу журнал ниже, когда он возвращает 401:
[GIN-debug] запрос перенаправления 301: /handler -> /hanlder/? Param1= что-то ¶m2= что-то другое
но я не вижу этот журнал, когда вызов из клиентского инструмента остальные API (или браузера)
Как вы, возможно, знаете из журнала, код на стороне сервера использует инфраструктуру go gin. Но поскольку в других случаях он работает нормально, я не думаю, что это проблема с кодом на стороне сервера.
Возвращаясь к коду C#, я попытался использовать HttpWebRequest с NetworkCredential вместо HttpClient, и я также пытаюсь использовать client.DefaultRequestHeaders.Authorization = auth, но я все еще получаю ту же ошибку.
Мне интересно, если кто-то видел это раньше или может помочь? Это будет действительно оценено.
1 ответ
В качестве обходного пути я могу изменить запрос, чтобы он был http://myservice.com/handler/?param1=something¶m2=somethingelse чтобы перенаправление не требовалось. Таким образом, он будет правильно авторизован.
Но, тем не менее, пока не выяснили, как сделать второй запрос для отправки с заголовком авторизации.