HttpListenerContext.Managed.cs 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. using System;
  2. using System.ComponentModel;
  3. using System.Security.Principal;
  4. using System.Text;
  5. using System.Threading.Tasks;
  6. using SocketHttpListener.Net.WebSockets;
  7. namespace SocketHttpListener.Net
  8. {
  9. public sealed unsafe partial class HttpListenerContext
  10. {
  11. private HttpConnection _connection;
  12. internal HttpListenerContext(HttpConnection connection)
  13. {
  14. _connection = connection;
  15. _response = new HttpListenerResponse(this);
  16. Request = new HttpListenerRequest(this);
  17. ErrorStatus = 400;
  18. }
  19. internal int ErrorStatus { get; set; }
  20. internal string ErrorMessage { get; set; }
  21. internal bool HaveError => ErrorMessage != null;
  22. internal HttpConnection Connection => _connection;
  23. internal void ParseAuthentication(System.Net.AuthenticationSchemes expectedSchemes)
  24. {
  25. if (expectedSchemes == System.Net.AuthenticationSchemes.Anonymous)
  26. return;
  27. string header = Request.Headers["Authorization"];
  28. if (string.IsNullOrEmpty(header))
  29. return;
  30. if (IsBasicHeader(header))
  31. {
  32. _user = ParseBasicAuthentication(header.Substring(AuthenticationTypes.Basic.Length + 1));
  33. }
  34. }
  35. internal IPrincipal ParseBasicAuthentication(string authData) =>
  36. TryParseBasicAuth(authData, out HttpStatusCode errorCode, out string username, out string password) ?
  37. new GenericPrincipal(new HttpListenerBasicIdentity(username, password), Array.Empty<string>()) :
  38. null;
  39. internal static bool IsBasicHeader(string header) =>
  40. header.Length >= 6 &&
  41. header[5] == ' ' &&
  42. string.Compare(header, 0, AuthenticationTypes.Basic, 0, 5, StringComparison.OrdinalIgnoreCase) == 0;
  43. internal static bool TryParseBasicAuth(string headerValue, out HttpStatusCode errorCode, out string username, out string password)
  44. {
  45. errorCode = HttpStatusCode.OK;
  46. username = password = null;
  47. try
  48. {
  49. if (string.IsNullOrWhiteSpace(headerValue))
  50. {
  51. return false;
  52. }
  53. string authString = Encoding.UTF8.GetString(Convert.FromBase64String(headerValue));
  54. int colonPos = authString.IndexOf(':');
  55. if (colonPos < 0)
  56. {
  57. // username must be at least 1 char
  58. errorCode = HttpStatusCode.BadRequest;
  59. return false;
  60. }
  61. username = authString.Substring(0, colonPos);
  62. password = authString.Substring(colonPos + 1);
  63. return true;
  64. }
  65. catch
  66. {
  67. errorCode = HttpStatusCode.InternalServerError;
  68. return false;
  69. }
  70. }
  71. public Task<HttpListenerWebSocketContext> AcceptWebSocketAsync(string subProtocol, int receiveBufferSize, TimeSpan keepAliveInterval)
  72. {
  73. return HttpWebSocket.AcceptWebSocketAsyncCore(this, subProtocol, receiveBufferSize, keepAliveInterval);
  74. }
  75. [EditorBrowsable(EditorBrowsableState.Never)]
  76. public Task<HttpListenerWebSocketContext> AcceptWebSocketAsync(string subProtocol, int receiveBufferSize, TimeSpan keepAliveInterval, ArraySegment<byte> internalBuffer)
  77. {
  78. WebSocketValidate.ValidateArraySegment(internalBuffer, nameof(internalBuffer));
  79. HttpWebSocket.ValidateOptions(subProtocol, receiveBufferSize, HttpWebSocket.MinSendBufferSize, keepAliveInterval);
  80. return HttpWebSocket.AcceptWebSocketAsyncCore(this, subProtocol, receiveBufferSize, keepAliveInterval, internalBuffer);
  81. }
  82. }
  83. }