簡體   English   中英

如何通過SslStream和TcpClient將有效的HTTPS請求發送到Web服務

[英]How to send valid HTTPS requests to a web service via SslStream and TcpClient

我實質上是在嘗試設置一個HTTPS客戶端,該客戶端可用於我正在開發的自動化測試API和其他Web服務。 我對使用套接字很熟悉,但是對在代碼中使用SSL / TLS卻不太了解。 我首先嘗試設置一個客戶端,該客戶端使用以下標頭向google.com發送HTTP請求: GET / HTTP/1.1

這個想法是通過加密連接從Google接收基本的HTTP響應。 使用未加密的HTTP時,這真的很容易-我什至可以通過端口80 telnet到google中,然后輸入GET / HTTP/1.1 ,我會收到一個不錯的HTTP響應標頭和HTML有效負載。 實現C / C#代碼以發出未加密的HTTP請求也不是很困難。 SSL使我很難受。

使用下面的代碼(完整的示例位於https://msdn.microsoft.com/zh-cn/library/system.net.security.sslstream.aspx?cs-save-lang=1&cs-lang=csharp#code-snippet -3 ),與MSDN提供的參考幾乎完全相同,因此我可以成功連接到google.com並驗證服務器證書:

        // Create a TCP/IP client socket.
        // machineName is the host running the server application.
        TcpClient client = new TcpClient(machineName, 443);
        Console.WriteLine("Client connected.");
        // Create an SSL stream that will close the client's stream.
        SslStream sslStream = new SslStream(
            client.GetStream(),
            false,
            new RemoteCertificateValidationCallback(ValidateServerCertificate),
            null
            );
        // The server name must match the name on the server certificate.
        try
        {
            sslStream.AuthenticateAsClient(serverName);
        }
        catch (AuthenticationException e)
        {
            Console.WriteLine("Exception: {0}", e.Message);
            if (e.InnerException != null)
            {
                Console.WriteLine("Inner exception: {0}", e.InnerException.Message);
            }
            Console.WriteLine("Authentication failed - closing the connection.");
            client.Close();
            return;
        }

問題是執行以下代碼時,ReadMessage(sslStream)指令掛起,因為很長一段時間我都沒有收到響應,而當響應最終出現時,它是一個空字符串:

        // Encode a test message into a byte array.
        // Signal the end of the message using the "<EOF>".
        byte[] messsage = Encoding.UTF8.GetBytes("GET / HTTP/1.1<EOF>");
        // Send hello message to the server. 
        sslStream.Write(messsage);
        sslStream.Flush();
        // Read message from the server.
        string serverMessage = ReadMessage(sslStream);
        Console.WriteLine("Server says: {0}", serverMessage);

因此,通過安全套接字連接發出此請求時,我無法收到我正在尋找的HTTP響應(或任何其他響應)。 從長遠來看,這個想法是開始使用此客戶端向我自己的API和Web服務發送自定義的HTTP請求,但是,即使我什至無法從google.com上獲得通用響應,我也肯定不會這樣做。 有誰知道為什么ReadMessage()函數超時或不提供任何響應? 該示例代碼看起來非常簡單,因此我很難理解自己在做什么。

立即引起我注意的一件事是,Microsoft示例未為sslStream.Write()提供“ count”參數,我認為這可能與您的問題有關。 還要注意, ReadMessage()似乎是您未提供定義的函數。 如果不知道ReadMessage()具體在做什么,則無法確定問題的確切原因。 我修改了提供的代碼,以發送HTTPS請求和讀取響應。 到目前為止,我嘗試過的網站似乎都可以正常工作。

        // Send request
        byte[] buffer = new byte[2048];
        int bytes;
        byte[] request = Encoding.UTF8.GetBytes(String.Format("GET https://{0}/  HTTP/1.1\r\nHost: {0}\r\n\r\n", serverName));
        sslStream.Write(request, 0, request.Length);
        sslStream.Flush();

        // Read response
        do
        {
            bytes = sslStream.Read(buffer, 0, buffer.Length);
            Console.Write(Encoding.UTF8.GetString(buffer, 0, bytes));
        } while (bytes == 2048);

另外,我還注意到sslStream.AuthenticateAsClient(serverName); 當然適用於許多Web服務; 但是,在訪問嚴格使用TLS1.2的網站時,我遇到了特別重載的問題。 嘗試sslStream.AuthenticateAsClient(serverName,null,SslProtocols.Tls12,false); 如果要啟用對嚴格的TLS1.2代理的支持。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM