Заголовок дайджест-аутентификации HttpClientHandler RFC 7616 с использованием неверного Uri - PullRequest
0 голосов
/ 07 сентября 2018

Я пытаюсь получить доступ к ресурсу на сервере Lighttpd, который обеспечивает, чтобы полный URI запроса совпадал с URI в заголовке запроса авторизации.Это указано в RFC 7616

. Сервер аутентификации ДОЛЖЕН гарантировать, что ресурс, указанный параметром "uri", совпадает с ресурсом, указанным в строке запроса;в противном случае сервер ДОЛЖЕН вернуть ошибку 400 Bad Request.(Поскольку это может быть признаком атаки, серверные
разработчики могут захотеть занести в журнал такие ошибки.) Цель
дублирования информации из URL-адреса запроса в этом поле состоит в том, чтобы
иметь дело с возможностью того, чтопромежуточный прокси-сервер может изменить строку запроса
клиента.Этот измененный (но предположительно семантически
эквивалентный) запрос не приведет к тому же дайджесту, что и вычисленный клиентом
.

Я использую библиотеку Flurl (v1.4), который является просто оболочкой для HttpClient.Однако HttpClientHandler из .Net.

Почему он использует базовый URI, а не полный URI?Это ошибка?Как мне сделать так, чтобы он использовал полный URI?

Я думал добавить еще один HttpMessageHandler в конвейер и изменить заголовок Authentication с полным URI, но HttpClientHandler не позволяет установить InnerHandler .

Полный Uri должен быть : http://base/resource.cgi?my=1&params=2

Но это то, что появляется в заголовке запроса:

Авторизация: дайджест имени пользователя= "user", realm = "serve", nonce = "5b911545: eaf4352d2113e5e4b1ca253bd70fd90a", uri = "/ base / resource.cgi" , cnonce = "bf7cf40f1289bc10bd84e00b0147008010044700801004010080100801000001", response =" cf3c731ec93f7e5928f19f880f8325ab "

, что приводит к 400 ошибочным запросам ответ.

My Flurl Code:

HttpClient Factory

    /// <summary>
    /// Custom factory to generate HttpClient and handler to use digest authentication and a continuous stream
    /// </summary>
    private class DigestHttpFactory : Flurl.Http.Configuration.DefaultHttpClientFactory
    {
        private CredentialCache CredCache { get; set; }

        public DigestHttpFactory(string url, string username, string password) : base()
        {
            Url = url;

            CredCache = new CredentialCache
            {
                { new Uri(Url), "Digest", new NetworkCredential(username, password) }
            };
        }

        private string Url { get; set; }

        public override HttpClient CreateHttpClient(HttpMessageHandler handler)
        {
            var client = base.CreateHttpClient(handler);
            client.Timeout = TimeSpan.FromMilliseconds(Timeout.Infinite); // To keep stream open indefinietly
            return client;
        }

        public override HttpMessageHandler CreateMessageHandler()
        {
            var handler = new HttpClientHandler
            {
                Credentials = CredCache.GetCredential(new Uri(Url), "Digest")
            };


            return handler;
        }
    }

Код запроса

public class MyConnection
{
    public string BaseUrl => "http://base/resource.cgi";

    public async Task ConnectAsync(CancellationToken cancellationToken = default(CancellationToken))
    {
        ConnectionCancellation = new CancellationTokenSource();

        var url = BaseUrl
            .SetQueryParam("my", 1)
            .SetQueryParam("params", 2)

        FlurlHttp.ConfigureClient(url, client =>
        {
            client.Configure(settings =>
            {
                settings.HttpClientFactory = new DigestHttpFactory(url, Username, Password);
            });
        });

        try
        {
            using (var getResponse = url.GetAsync(cancellationToken, HttpCompletionOption.ResponseHeadersRead))
            {
                var responseMessage = await getResponse;

                using (var linkedCts = CancellationTokenSource.CreateLinkedTokenSource(ConnectionCancellation.Token, cancellationToken))
                using (var stream = await responseMessage.Content.ReadAsStreamAsync())
                    await Process(stream, linkedCts.Token);
            }
        }
        catch (OperationCanceledException ex)
        {
            throw ex;
        }
        catch (Exception ex)
        {
            throw ex;
        }
    }
}

1 Ответ

0 голосов
/ 07 сентября 2018

Похоже, что это действительно ошибка с реализацией Microsoft RFC:

Классы System.Net не включают строку запроса в 'Uri' атрибут заголовка дайджест-аутентификации. Это нарушение RFC и некоторые реализации веб-сервера отклоняют эти запросы.

В этом сообщении подробно описан обходной путь, взятый из этого ответа .

...