通过C#中的SSLStream发送GET命令

本文关键字:GET 命令 发送 SSLStream 中的 通过 | 更新日期: 2023-09-27 18:21:58

我正在编写一个http自动化框架,我的问题是使用经过身份验证的http安全连接进行通信。经过一些研究,我在C#中发现了SslStream对象,这使得我可以轻松地与现有的客户端架构集成。问题是;尽管能够验证我与给定web服务器的连接,但任何"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.1200OK"和一些头部信息。除了标头之外,不会返回任何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;
    }

出于测试目的,我正在尝试访问谷歌安卓开发者门户(因为它使用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

谢谢你花时间来看我的问题,我很感激!如果你想从我这里得到更多的信息,我很乐意提供。由于我认为我的错误可能是一个愚蠢的格式问题,我认为不需要更多的信息。

再次感谢!

通过C#中的SSLStream发送GET命令

readStream函数在读取的缓冲区不足时终止。

然而,这只是意味着现在没有更多的可用数据;未来可能会有更多可用的。

stream.Read返回零字节之前不要停止读取。

读取HTTP消息时:

  • 如果你在标题中,你应该一直读到标题的末尾(也就是说,当它遇到两个连续的CRLF序列时,即空行)。然后你应该开始阅读正文
  • 当您在邮件正文中时:
    • 如果有Content-Length标头,则应继续读取,直到读取到此标头所需的字节数为止
    • 如果您使用的是块传输编码(这里的情况是:Transfer-Encoding: chunked),您应该查找0终止字符(但您还必须分析所有块并将它们粘合在一起,因为您不想在实际内容包含0时停止)

一般来说,无法区分突然关闭的TCP连接和不发送任何内容的TCP连接。无论您是否从stream.Read中读取了0个字节,要知道您已经收到了所有应该收到的消息,唯一的方法就是进行此分析。(你可能会发现,处理分块传输编码可能会让你自己的库比你想要的轻一点。)