Почему мой Http-клиент делает 2 запроса при указании учетных данных? - PullRequest
11 голосов
/ 14 июня 2011

Я создал RESTful webservice (WCF), где проверяю учетные данные при каждом запросе. Один из моих клиентов - это приложение для Android, и все хорошо на стороне сервера. Я получаю запрос, и если у него есть правильный заголовок - я обрабатываю его и т. Д.

Теперь я создал клиентское приложение, которое использует этот сервис. Вот как я делаю GET:

// Create the web request  
            var request = WebRequest.Create(Context.ServiceURL + uri) as HttpWebRequest;

            if (request != null)
            {
                request.ContentType = "application/json";

                // Add authentication to request  
                request.Credentials = new NetworkCredential(Context.UserName, Context.Password);

                // Get response  
                using (var response = request.GetResponse() as HttpWebResponse)
                {
                    // Get the response stream  
                    if (response != null)
                    {
                        var reader = new StreamReader(response.GetResponseStream());

                        // Console application output
                        var s = reader.ReadToEnd();

                        var serializer = new JavaScriptSerializer();
                        var returnValue = (T)serializer.Deserialize(s, typeof(T));

                        return returnValue;
                    }
                }
            }

Итак, этот код получает мой ресурс и десериализует его. Как вы видите - я передаю полномочия в моем звонке.

Затем при отладке на стороне сервера я заметил, что каждый раз я получаю 2 запроса - один без заголовка аутентификации, а затем сервер отправляет ответный ответ, а второй запрос отправляется с учетными данными. Я думаю, что это плохо для моего сервера - я бы предпочел не совершать никаких обходов. Как мне сменить клиента, чтобы этого не произошло? Смотрите скриншот Fiddler

First BAD request

Second GOOD request

EDIT

Это код JAVA, который я использую с Android - он не выполняет двойной вызов:

MyHttpResponse response = new MyHttpResponse();
        HttpClient client = mMyApplication.getHttpClient();

        try
        {
            HttpGet request = new HttpGet(serviceURL + url);
            request.setHeader(new BasicHeader(HTTP.CONTENT_TYPE, "application/json"));
            request.addHeader("Authorization", "Basic " + Preferences.getAuthorizationTicket(mContext));

            ResponseHandler<String> handler = new BasicResponseHandler();
            response.Body = client.execute(request, handler);
            response.Code = HttpURLConnection.HTTP_OK;
            response.Message = "OK";
        }
        catch (HttpResponseException e)
        {
            response.Code = e.getStatusCode();
            response.Message = e.getMessage();

            LogData.InsertError(mContext, e);
        }

Ответы [ 3 ]

10 голосов
/ 14 июня 2011

В первоначальном запросе никогда не указывается базовый заголовок для аутентификации.Кроме того, поскольку указана область, вы должны получить ее с сервера.Поэтому вы должны спросить один раз: «эй, мне нужны эти вещи», и сервер говорит: «Кто вы? Целью ответа является« безопасная зона »».(потому что область означает что-то здесь) То, что вы добавили это здесь:

request.Credentials = new NetworkCredential(Context.UserName, Context.Password);

, не означает, что оно будет обязательно прикреплено к запросу каждый раз.

Затем вы отвечаетеимя пользователя / пароль (в данном случае вы используете BASIC, поэтому base64 кодируется как имя: пароль), а сервер декодирует его и говорит: «Хорошо, все ясно, вот ваши данные».

Этобудет происходить на регулярной основе, и вы ничего не можете с этим поделать.Я бы посоветовал вам также включить HTTPS, поскольку аутентификация происходит в виде простого текста через Интернет.(на самом деле то, что вы показываете, кажется, находится через интранет, но если вы делаете заходите в Интернет, сделайте его https).

Вот ссылка на Википедию, которая может помочь вам в дальнейшем: http://en.wikipedia.org/wiki/Basic_access_authentication

9 голосов
/ 14 июня 2011

Хорошо, я понял. Я вручную устанавливаю HttpHeader вместо использования request.Credentials

request.Headers.Add(HttpRequestHeader.Authorization, "Basic " + Convert.ToBase64String(Encoding.UTF8.GetBytes(Context.UserName + ":" + Context.Password)));

Теперь я вижу только отдельные запросы, как и ожидалось ..

0 голосов
/ 24 октября 2018

В качестве опции вы можете использовать PreAuthenticate свойство HttpClientHandler .Для этого потребуется на пару строк больше

            var client = new HttpClient(new HttpClientHandler
            {
                Credentials = yourCredentials,
                PreAuthenticate = true
            });

. При использовании этого подхода только первый запрос отправляется без учетных данных, но все остальные запросы в порядке.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...