c# – 检查请求是否来自套接字侦听器中的HTTP或HTTPS

前端之家收集整理的这篇文章主要介绍了c# – 检查请求是否来自套接字侦听器中的HTTP或HTTPS前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我有多线程异步套接字监听器.我想检查请求是否安全.但我想在AcceptCallBack方法中检查不是ReceiveCallBack.

我会这样做,因为我希望我的代码适用于HTTP和HTTPS.如果请求来自HTTPS,我将继续使用经过身份验证的SslStream而不是原始套接字.

这是我的代码

  1. using System;
  2. using System.Net;
  3. using System.Net.Sockets;
  4. using System.Threading;
  5. using System.Text;
  6.  
  7. namespace LearnRequestType
  8. {
  9. class StackOverFlow
  10. {
  11. private static readonly ManualResetEvent _manualResetEvent = new ManualResetEvent(false);
  12.  
  13. private void StartListening()
  14. {
  15. IPEndPoint localEndPoint = new IPEndPoint(IPAddress.Any,9002);
  16.  
  17. if (localEndPoint != null)
  18. {
  19. Socket listener = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
  20.  
  21. if (listener != null)
  22. {
  23. listener.Bind(localEndPoint);
  24. listener.Listen(10);
  25.  
  26. Console.WriteLine("Socket listener is running...");
  27.  
  28. listener.BeginAccept(new AsyncCallback(AcceptCallback),listener);
  29. }
  30. }
  31. }
  32.  
  33. private void AcceptCallback(IAsyncResult ar)
  34. {
  35. _manualResetEvent.Set();
  36.  
  37. Socket listener = (Socket)ar.AsyncState;
  38.  
  39. Socket handler = listener.EndAccept(ar);
  40.  
  41. StateObject state = new StateObject();
  42. state.workSocket = handler;
  43.  
  44. // I want to understand if request comes from HTTP or HTTPS before this line.
  45. handler.BeginReceive(state.buffer,StateObject.BufferSize,new AsyncCallback(ReceiveCallback),state);
  46.  
  47. listener.BeginAccept(new AsyncCallback(AcceptCallback),listener);
  48. }
  49.  
  50. private void ReceiveCallback(IAsyncResult result)
  51. {
  52. StateObject state = (StateObject)result.AsyncState;
  53. Socket handler = state.workSocket;
  54.  
  55. string clientIP = ((IPEndPoint)handler.RemoteEndPoint).Address.ToString();
  56.  
  57. int numBytesReceived = handler.EndReceive(result);
  58.  
  59. if (!handler.Connected)
  60. {
  61. handler.Close();
  62. return;
  63. }
  64.  
  65. // Read incoming data...
  66. if (numBytesReceived > 0)
  67. {
  68. state.sb.Append(Encoding.ASCII.GetString(state.buffer,numBytesReceived));
  69.  
  70. // Read incoming data line by line.
  71. string[] lines = state.sb.ToString().Split('\n');
  72.  
  73. if (lines[lines.Length - 1] == "<EOF>")
  74. {
  75. // We received all data. Do something...
  76.  
  77. }
  78. else
  79. {
  80. // We didn't receive all data. Continue reading...
  81. handler.BeginReceive(state.buffer,state.buffer.Length,SocketFlags.None,state);
  82. }
  83. }
  84. }
  85. }
  86. }
  87.  
  88. public class StateObject
  89. {
  90. public Socket workSocket = null;
  91. public const int BufferSize = 256;
  92. public byte[] buffer = new byte[BufferSize];
  93. public StringBuilder sb = new StringBuilder();
  94. }

如果我更改AcceptCallBack方法和StateObject类:

  1. private void AcceptCallback(IAsyncResult ar)
  2. {
  3. _manualResetEvent.Set();
  4.  
  5. Socket listener = (Socket)ar.AsyncState;
  6.  
  7. Socket handler = listener.EndAccept(ar);
  8.  
  9. try
  10. {
  11. sslStream = new SslStream(new NetworkStream(handler,true));
  12.  
  13. // try to authenticate
  14. sslStream.AuthenticateAsServer(_cert,false,System.Security.Authentication.SslProtocols.Tls,true);
  15.  
  16. state.workStream = sslStream;
  17. state.workStream.ReadTimeout = 100000;
  18. state.workStream.WriteTimeout = 100000;
  19.  
  20. if (state.workStream.IsAuthenticated)
  21. {
  22. state.workStream.BeginRead(state.buffer,ReceiveCallback,state);
  23. }
  24. }
  25. catch (IOException ex)
  26. {
  27. // ıf we get handshake Failed due to an unexpected packet format,this means incoming data is not HTTPS
  28. // Continue with socket not sslstream
  29. state.workSocket = handler;
  30. handler.BeginReceive(state.buffer,state);
  31. }
  32.  
  33. StateObject state = new StateObject();
  34. state.workStream = handler;
  35.  
  36. handler.BeginReceive(state.buffer,state);
  37.  
  38. listener.BeginAccept(new AsyncCallback(AcceptCallback),listener);
  39. }
  40.  
  41. public class StateObject
  42. {
  43. public Socket workSocket = null;
  44. public SslStream workStream = null;
  45. public const int BufferSize = 1024;
  46. public byte[] buffer = new byte[BufferSize];
  47. public StringBuilder sb = new StringBuilder();
  48. }

我可以决定传入的数据类型是HTTP还是HTTPS,但如果是HTTP,它每次都会被catch块处理,因此会降低应用程序性能.

还有另一种方式吗?

解决方法

如果我理解正确,您有一个端口,客户端可以使用HTTP或HTTPS进行连接,并且您希望在传输任何数据之前立即知道请求是如何进行的.

在从客户端接收数据之前无法知道这一点. HTTP和HTTPS是TCP之上的协议,它们不能在较低的协议级别上工作,因此没有标志或任何可以说明使用哪种协议的东西.此外,HTTPS只是包含在TLS / SSL流中的普通HTTP流.

您必须读取数据并根据使用的协议确定.或者你必须有单独的HTTP和HTTPS端口,这将使这一点变得微不足道.

要检测它是否是TLS / SSL,您可以查看几个字节并查看其中的内容.The TLS specification表示客户端Hello数据包以协议版本启动,协议版本以两个uint8发送.由于HTTP请求总是将动词作为第一个,因此您可以轻松检查是否有一些第一个字节是字符,然后尝试SSLStream(如果不是).

另请注意,如果您在套接字上启动SSLStream,它可能会从套接字中读取,这将消耗HTTP请求的开头,您无法正常处理它.

所以在你的Accept回调中使用这样的东西:

  1. Socket handler = listener.EndAccept(ar);
  2. byte[] tmp = new byte[2];
  3. handler.Receive(tmp,2,SocketFlags.Peek);
  4. if (!Char.IsLetter((char)tmp[0]) || !Char.IsLetter((char)tmp[1]))
  5. {
  6. // Doesn't start with letters,so most likely not HTTP
  7. } else {
  8. // Starts with letters,should be HTTP
  9. }

如果您想确保它是TLS / SSL,您可以查看this question on SO

猜你在找的C#相关文章