//------------------------------------------------------------------------------ // 此代码版权(除特别声明或在XREF结尾的命名空间的代码)归作者本人若汝棋茗所有 // 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权 // CSDN博客:https://blog.csdn.net/qq_40374647 // 哔哩哔哩视频:https://space.bilibili.com/94253567 // Gitee源代码仓库:https://gitee.com/RRQM_Home // Github源代码仓库:https://github.com/RRQM // API首页:https://www.yuque.com/rrqm/touchsocket/index // 交流QQ群:234762506 // 感谢您的下载和使用 //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ using System; using System.Collections.Generic; using System.Text; namespace TouchSocket.Http { /// /// 处理代理认证凭证 /// internal class AuthenticationChallenge { /// /// 构造 /// /// 服务器返回的凭证认证类型 /// 基本凭证用户名密码 /// 暂时不知道是什么 public AuthenticationChallenge(string value, NetworkCredential credential, uint nonceCount = 0) { Parse(value, credential); NonceCount = nonceCount; } /// /// 暂时不知 /// public uint NonceCount { get; set; } /// /// 其实用不用他都一样 /// public Dictionary Parameters { get; set; } /// /// 凭证类型 /// public AuthenticationType Type { get; set; } /// /// 转换成凭证本文 /// /// /// public override string ToString() { if (Type == AuthenticationType.Basic) return ToBasicString(); else throw new Exception("该凭证类型不支持"); } private void Parse(string value, NetworkCredential credential) { var chal = value.Split(new[] { ' ' }, 2); if (chal.Length != 2) throw new Exception("该凭证类型不支持"); var schm = chal[0].ToLower(); Parameters = ParseParameters(chal[1]); if (Parameters.ContainsKey("username") == false) Parameters.Add("username", credential.Username); if (Parameters.ContainsKey("password") == false) Parameters.Add("password", credential.Password); /* * Basic基本类型貌似只需要用户名密码即可 * if (this.parameters.ContainsKey("uri") == false) this.parameters.Add("uri", credential.Domain);*/ if (schm == "basic") { Type = AuthenticationType.Basic; } else throw new Exception("该凭证类型不支持"); } private Dictionary ParseParameters(string value) { var res = new Dictionary(); IEnumerable values = SplitHeaderValue(value, ','); foreach (var param in values) { var i = param.IndexOf('='); var name = i > 0 ? param.Substring(0, i).Trim() : null; var val = i < 0 ? param.Trim().Trim('"') : i < param.Length - 1 ? param.Substring(i + 1).Trim().Trim('"') : string.Empty; res.Add(name, val); } return res; } private IEnumerable SplitHeaderValue(string value, params char[] separators) { var len = value.Length; var end = len - 1; var buff = new StringBuilder(32); var escaped = false; var quoted = false; for (var i = 0; i <= end; i++) { var c = value[i]; buff.Append(c); if (c == '"') { if (escaped) { escaped = false; continue; } quoted = !quoted; continue; } if (c == '\\') { if (i == end) break; if (value[i + 1] == '"') escaped = true; continue; } if (Array.IndexOf(separators, c) > -1) { if (quoted) continue; buff.Length -= 1; yield return buff.ToString(); buff.Length = 0; continue; } } yield return buff.ToString(); } private string ToBasicString() { var userPass = $"{Parameters["username"]}:{Parameters["password"]}"; var cred = Convert.ToBase64String(Encoding.UTF8.GetBytes(userPass)); return "Basic " + cred; } } }