Отправка команд GET через SSLStream в C #? - PullRequest
3 голосов
/ 28 января 2012

Я пишу среду автоматизации http, и моя проблема связана с аутентифицированным http защищенным соединением. Проведя некоторые исследования, я обнаружил объект SslStream в C #, который облегчает интеграцию с моей существующей клиентской архитектурой. Проблема в; несмотря на то, что я могу аутентифицировать мое соединение с данным веб-сервером, любые команды «GET [website] HTTP / 1.1», похоже, возвращают только заголовки, а не реальные веб-страницы.

У меня такое чувство, что я не формирую свои веб-запросы должным образом, но я действительно не знаю. Я занимаюсь исследованиями все утро и не могу найти очень много ресурсов по этому конкретному вопросу. Вот пример кода из моего проекта:

    private IAsyncResult Request(HttpRequestToken token, ReceiveEvent callback) 
    {
        if (token == null)
            throw new Exception("Error. No request information provided. Aborting operation.");

        //Setup the TCP Information. (_port is set to 443 for SSL purposes)
        var client = new TcpClient(token.Host, _port);

        //Get a handle to a networkstream for writing data.
        var requestStream = new SslStream(client.GetStream(), false, null);

        //Authenticate the request
        requestStream.AuthenticateAsClient(token.Host);

        //Translate the data.
        byte[] sendBuffer = UTF8Encoding.UTF8.GetBytes(token.ToString());

        //NOTE: The results of the above command will look like this:
        //GET [website] HTTP/1.1
        //Host: [host]
        //passive: true
        //Accepts: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
        //User-Agent: Mozilla/5.0 (Windows NT 6.1; rv:2.0.1) Gecko/20100101 Firefox/4.0.1 Fennec/2.0.1

        //Send the data.
        requestStream.Write(sendBuffer);

        //Get the string value with a function that just iterates over the stream.
        string val = readStream(requestStream);

        //Breakpoint here, this code is not complete but "functions".
        return null;
    }

По сути, результаты моего кода просто вернут "HTTP / 1.1 200 OK" с некоторой информацией заголовка. HTML или что-либо еще не возвращается за пределами заголовков.

По запросу, вот еще некоторая информация:

    private string readStream(Stream stream)
    {
        byte[] resultBuffer = new byte[2048];
        string value = "";
        //requestStream.BeginRead(resultBuffer, 0, resultBuffer.Length, new AsyncCallback(ReadAsyncCallback), new result() { buffer = resultBuffer, stream = requestStream, handler = callback, asyncResult = null });
        do
        {
            try
            {
                int read = stream.Read(resultBuffer, 0, resultBuffer.Length);
                value += UTF8Encoding.UTF8.GetString(resultBuffer, 0, read);

                if (read < resultBuffer.Length)
                    break;
            }
            catch { break; }
        } while (true);
        return value;
    }

В целях тестирования я пытаюсь получить доступ к порталу Google для разработчиков Android (поскольку он использует SSL). Это просто для загрузки страницы входа в систему, в этот момент никакая информация не передается, кроме запроса загрузки страницы. Вот мой точный запрос.

GET https://accounts.google.com/ServiceLogin HTTP/1.1
Host: accounts.google.com
passive: true
nui: 1
continue: https://market.android.com/publish
followup: https://market.android.com/publish
Accepts: text/html,application/xhtml+xml,application/xml;q=0.9,
User-Agent: Mozilla/5.0 (Windows NT 6.1; rv:2.0.1) Gecko/20100101 Firefox/4.0.1 Fennec/2.0.1

Это ответ сервера:

HTTP/1.1 200 OK
Content-Type: text/html; charset=UTF-8
Strict-Transport-Security: max-age=2592000; includeSubDomains
Set-Cookie: GAPS=1:0bFTJDze2Zz8WL_x3F7-OQfOjEOycg:rG8nLpBEwdG67aU_;Path=/;Expires=Mon, 27-Jan-2014 21:31:48 GMT;Secure;HttpOnly
Set-Cookie: GALX=KaXGmr2TI-I;Path=/;Secure
Cache-control: no-cache, no-store
Pragma: no-cache
Expires: Mon, 01-Jan-1990 00:00:00 GMT
X-Frame-Options: Deny
X-Auto-Login: realm=com.google&args=continue%3Dhttps%253A%252F%252Faccounts.google.com%252FManageAccount
Transfer-Encoding: chunked
Date: Sat, 28 Jan 2012 21:31:48 GMT
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Server: GSE

Спасибо, что нашли время посмотреть на мой вопрос, я ценю это! Если вам нужна дополнительная информация от меня, я с радостью ее предоставлю. Поскольку я считаю, что моя ошибка, вероятно, глупая проблема с форматированием, я не думал, что потребуется дополнительная информация.

Опять спасибо!

Ответы [ 2 ]

8 голосов
/ 29 января 2012

Функция readStream завершается, когда она читает меньше, чем полный буфер.

Однако это просто означает, что больше нет доступных данных; там может быть больше доступных в будущем.

Не прекращайте чтение, пока stream.Read не вернет ноль байтов.

3 голосов
/ 29 января 2012

При чтении сообщения HTTP:

  • Если вы находитесь в заголовке, вы должны продолжать чтение до конца заголовка (то есть, когда он встречает две последовательные последовательности CRLF,т.е. пустая строка).Затем вы должны начать читать тело.
  • Когда вы находитесь в теле сообщения:
    • Если есть заголовок Content-Length, вы должны продолжать читать, пока не прочитаете числоот этого заголовка ожидается байт.
    • Если вы используете Chunked Transfer Encoding (в данном случае: Transfer-Encoding: chunked), вы должны искать символ завершения 0 (новам также придется проанализировать все куски и склеить их вместе, так как вы не хотите останавливаться, когда фактический контент содержит 0).

ТамВ общем, нет никакого способа отличить внезапно закрытое TCP-соединение от того, которое ничего не отправляет.Читаете ли вы 0 байтов из stream.Read или нет, единственный способ узнать, что у вас есть все сообщения, которые вы должны были получить, - провести этот анализ.(Вы можете обнаружить, что работа с кодировкой передачи по частям может сделать вашу собственную библиотеку немного менее легкой, чем вам бы хотелось.)

...