AuthenticationChallenge.cs 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. //------------------------------------------------------------------------------
  2. // 此代码版权(除特别声明或在XREF结尾的命名空间的代码)归作者本人若汝棋茗所有
  3. // 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
  4. // CSDN博客:https://blog.csdn.net/qq_40374647
  5. // 哔哩哔哩视频:https://space.bilibili.com/94253567
  6. // Gitee源代码仓库:https://gitee.com/RRQM_Home
  7. // Github源代码仓库:https://github.com/RRQM
  8. // API首页:https://www.yuque.com/rrqm/touchsocket/index
  9. // 交流QQ群:234762506
  10. // 感谢您的下载和使用
  11. //------------------------------------------------------------------------------
  12. //------------------------------------------------------------------------------
  13. using System;
  14. using System.Collections.Generic;
  15. using System.Text;
  16. namespace TouchSocket.Http
  17. {
  18. /// <summary>
  19. /// 处理代理认证凭证
  20. /// </summary>
  21. internal class AuthenticationChallenge
  22. {
  23. /// <summary>
  24. /// 构造
  25. /// </summary>
  26. /// <param name="value">服务器返回的凭证认证类型</param>
  27. /// <param name="credential">基本凭证用户名密码</param>
  28. /// <param name="nonceCount">暂时不知道是什么</param>
  29. public AuthenticationChallenge(string value, NetworkCredential credential, uint nonceCount = 0)
  30. {
  31. Parse(value, credential);
  32. NonceCount = nonceCount;
  33. }
  34. /// <summary>
  35. /// 暂时不知
  36. /// </summary>
  37. public uint NonceCount { get; set; }
  38. /// <summary>
  39. /// 其实用不用他都一样
  40. /// </summary>
  41. public Dictionary<string, string> Parameters { get; set; }
  42. /// <summary>
  43. /// 凭证类型
  44. /// </summary>
  45. public AuthenticationType Type { get; set; }
  46. /// <summary>
  47. /// 转换成凭证本文
  48. /// </summary>
  49. /// <returns></returns>
  50. /// <exception cref="Exception"></exception>
  51. public override string ToString()
  52. {
  53. if (Type == AuthenticationType.Basic)
  54. return ToBasicString();
  55. else
  56. throw new Exception("该凭证类型不支持");
  57. }
  58. private void Parse(string value, NetworkCredential credential)
  59. {
  60. var chal = value.Split(new[] { ' ' }, 2);
  61. if (chal.Length != 2)
  62. throw new Exception("该凭证类型不支持");
  63. var schm = chal[0].ToLower();
  64. Parameters = ParseParameters(chal[1]);
  65. if (Parameters.ContainsKey("username") == false)
  66. Parameters.Add("username", credential.Username);
  67. if (Parameters.ContainsKey("password") == false)
  68. Parameters.Add("password", credential.Password);
  69. /*
  70. * Basic基本类型貌似只需要用户名密码即可
  71. * if (this.parameters.ContainsKey("uri") == false)
  72. this.parameters.Add("uri", credential.Domain);*/
  73. if (schm == "basic")
  74. {
  75. Type = AuthenticationType.Basic;
  76. }
  77. else
  78. throw new Exception("该凭证类型不支持");
  79. }
  80. private Dictionary<string, string> ParseParameters(string value)
  81. {
  82. var res = new Dictionary<string, string>();
  83. IEnumerable<string> values = SplitHeaderValue(value, ',');
  84. foreach (var param in values)
  85. {
  86. var i = param.IndexOf('=');
  87. var name = i > 0 ? param.Substring(0, i).Trim() : null;
  88. var val = i < 0
  89. ? param.Trim().Trim('"')
  90. : i < param.Length - 1
  91. ? param.Substring(i + 1).Trim().Trim('"')
  92. : string.Empty;
  93. res.Add(name, val);
  94. }
  95. return res;
  96. }
  97. private IEnumerable<string> SplitHeaderValue(string value, params char[] separators)
  98. {
  99. var len = value.Length;
  100. var end = len - 1;
  101. var buff = new StringBuilder(32);
  102. var escaped = false;
  103. var quoted = false;
  104. for (var i = 0; i <= end; i++)
  105. {
  106. var c = value[i];
  107. buff.Append(c);
  108. if (c == '"')
  109. {
  110. if (escaped)
  111. {
  112. escaped = false;
  113. continue;
  114. }
  115. quoted = !quoted;
  116. continue;
  117. }
  118. if (c == '\\')
  119. {
  120. if (i == end)
  121. break;
  122. if (value[i + 1] == '"')
  123. escaped = true;
  124. continue;
  125. }
  126. if (Array.IndexOf(separators, c) > -1)
  127. {
  128. if (quoted)
  129. continue;
  130. buff.Length -= 1;
  131. yield return buff.ToString();
  132. buff.Length = 0;
  133. continue;
  134. }
  135. }
  136. yield return buff.ToString();
  137. }
  138. private string ToBasicString()
  139. {
  140. var userPass = $"{Parameters["username"]}:{Parameters["password"]}";
  141. var cred = Convert.ToBase64String(Encoding.UTF8.GetBytes(userPass));
  142. return "Basic " + cred;
  143. }
  144. }
  145. }