在 C# 中通过 SSLStream 发送 GET 命令?

发布于 2024-12-29 12:55:55 字数 3739 浏览 2 评论 0原文

我正在编写一个 http 自动化框架,我的问题是与经过身份验证的 http 安全 连接进行通信。经过一些研究后,我发现了 C# 中的 SslStream 对象,它可以轻松地与我现有的客户端架构集成。问题是;尽管能够验证我与给定 Web 服务器的连接,但任何“GET [网站] 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

感谢您花时间查看我的问题,非常感谢!如果您想从我这里获得更多信息,我很乐意提供。因为我相信我的错误可能是一个愚蠢的格式问题,所以我认为不需要更多信息。

再次感谢!

I am writing an http automation framework and my problem is communicating with an authenticated http secured connection. After doing some research, I discovered the SslStream object in C# which made for easy integration with my existing client architecture. The problem is; despite being able to authenticate my connection with a given web server, any "GET [website] HTTP/1.1" commands seem to only return headers and not actual web pages.

I have a feeling that I am not forming my web requests properly, but I really don't know. I have been doing research all morning and cannot find very many resources on this particular issue. Here is a code sample from my project:

    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;
    }

Essentially, the results of my code will just return an "HTTP/1.1 200 OK" with some header information. No HTML or anything else is returned beyond the headers.

As Requested, Here is some more info:

    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;
    }

For testing purposes, I am trying to access the google android developer portal (since it uses SSL). This is simply to load the login page, no information is even being transmitted at this point other than a page load request. Here is my exact request.

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

This is the server response:

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

Thank you for taking the time to look at my question, I appreciate it! If you would like more information from me, I am happy to give it. Since I believe my mistake is probably a silly format-issue I didn't think more information would be required.

Again, thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

踏月而来 2025-01-05 12:55:55

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

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

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

The readStream function terminates when it reads less than a full buffer.

However, this just means that there is no more data available now; there might be more available in the future.

Don't stop reading until stream.Read returns zero bytes.

不醒的梦 2025-01-05 12:55:55

读取 HTTP 消息时:

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

通常没有办法区分突然关闭的 TCP 连接和不发送任何内容的连接。无论您是否从 stream.Read 读取 0 个字节,了解您是否已收到应收到的所有消息的唯一方法就是进行此分析。 (您可能会发现处理分块传输编码可能会使您自己的库比您想要的更轻量级。)

When reading an HTTP message:

  • If you're in the header, you should keep reading until the end of the header (that is, when it encounters two consecutive CRLF sequences, i.e. an empty line). You should then start reading the body.
  • When you're in the message body:
    • If there is a Content-Length header, you should keep reading until you've read the number of bytes expected from this header.
    • If you're using Chunked Transfer Encoding (which is your case here: Transfer-Encoding: chunked), you should look for the 0 termination character (but you'll also have to analyse all the chunks and glue them together, since you don't want to stop when the actual content contains a 0).

There is in general no way to distinguish a TCP connection closed abruptly from one that just isn't sending anything. Whether you read 0 bytes from stream.Read or not, the only way to know that you have all the message you should have received is to do this analysis. (You may find that dealing with chunked transfer encoding may make your own library a bit less lightweight than you'd like.)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文