HTTP SDK工具类,用来向服务端发送HTTP请求,请求支持POST/GET方式。如果提供了AccessKey和SecurityKey参数信息,它能够在内部将请求消息进行签名处理,然后向CSB服务端发送进行验证和调用。
# 签名机制的说明
如果CSB 控制台发布出来的HTTP 服务声明需要鉴权处理,则客户端调用该服务试CSB 要对每个访问请求进行身份验证。这就要求客户端无论使用HTTP 还是HTTPS协议提交请求,都需要在请求中包含签名(Signature)信息。 CSB通过使用Access Key ID 和Access Key Secret进行对称加密的方法来验证请求的发送者身份。 Access Key ID 和Access Key Secret由在管理控制台在服务订购时候指定和确认,HTTP SDK在访问时,按照下面的方法对请求进行签名处理:
1 使用请求参数构造规范化的请求字符串(Canonicalized Query String)。 a. 按照参数名称的字典顺序对请求中所有的请求参数,包括上文中中描述的“公共请求参数”(但不包括_api_signature 参数本身)和给定了的请求接口的自定义参数进行排序。 说明:当使用GET方法提交请求时,这些参数就是请求URI中的参数部分(即URI 中“?”之后由“&”连接的部分)。
b. 参数名称和值使用英文等号(=)进行连接。再把英文等号连接得到的字符串按参数名称的字典顺序依次使用&符号连接,即得到规范化请求字符串。 注意:请求参数是原始的name-value,即不能进行URL Encode等操作。
2 按照RFC2104 的定义,使用上述用于签名的字符串计算签名HMAC 值。注意:计算签名时使用的Key 就是用户持有的SecretKey,使用的哈希算法是SHA1。
3 按照Base64编码规则把上面的HMAC值编码成字符串,即得到签名值(Signature)。
4 将得到的签名值作为_api_signature参数添加到请求参数中,即完成对请求签名的过程。
HTTP请求封装类
1 namespace CSBSDK.NET 2 { 3 using System; 4 using System.Collections.Generic; 5 using System.IO; 6 using System.Net; 7 using System.Net.Http; 8 using System.Net.Security; 9 using System.Security.Cryptography.X509Certificates; 10 using System.Text; 11 using System.Linq; 12 public class HttpCaller 13 { 14 private static bool CheckValidationResult(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors errors) 15 { 16 return true; 17 } 18 protected static FormUrlEncodedContent createformdata(Dictionary<string, string> ps) { 19 var list = ps.ToList<KeyValuePair<string, string>>(); 20 var data = new FormUrlEncodedContent(list); 21 return data; 22 23 } 24 25 protected static string createPost(Dictionary<string, string> ps) 26 { 27 28 StringBuilder builder = new StringBuilder(); 29 foreach (KeyValuePair<string, string> pair in ps) 30 { 31 32 builder.Append(string.Format("{0}={1}&", pair.Key, pair.Value)); 33 } 34 string str = builder.ToString(); 35 if (str.EndsWith("&")) 36 { 37 str = str.Substring(0, str.Length - 1); 38 } 39 return str; 40 } 41 42 public static string doPost(string requestURL, string apiName, string version, Dictionary<string, string> paramsMap, string accessKey, string securityKey) 43 { 44 validateParams(apiName, accessKey, securityKey); 45 Dictionary<string, string> dictionary = parseUrlParamsMap(requestURL); 46 if (paramsMap != null) 47 { 48 foreach (KeyValuePair<string, string> pair in paramsMap) 49 { 50 if (!dictionary.ContainsKey(pair.Key)) 51 { 52 dictionary[pair.Key] = pair.Value; 53 } 54 } 55 } 56 requestURL = trimUrl(requestURL); 57 Dictionary<string, string> ps = newParamsMap(dictionary, apiName, version, accessKey, securityKey); 58 Dictionary<string, string> httpheaderkeys = new Dictionary<string, string> 59 { 60 { 61 "_api_name", 62 ps["_api_name"] 63 }, 64 { 65 "_api_timestamp", 66 ps["_api_timestamp"] 67 }, 68 { 69 "_api_access_key", 70 ps["_api_access_key"] 71 }, 72 { 73 "_api_signature", 74 ps["_api_signature"] 75 }, 76 { 77 "_api_version", 78 ps["_api_version"] 79 } 80 81 }; 82 83 string parameters = createPost(ps); 84 //var content = createformdata(ps); 85 return HttpPOST(requestURL, parameters, httpheaderkeys); 86 } 87 88 public static string Http(string url, string parameters, Encoding charset, NetworkCredential _credentials, Dictionary<string, string> keys, string ContentType, string methed) 89 { 90 HttpWebRequest request = null; 91 HttpWebResponse response; 92 ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(HttpCaller.CheckValidationResult); 93 request = WebRequest.Create(url) as HttpWebRequest; 94 request.ProtocolVersion = HttpVersion.Version11; 95 request.Method = methed; 96 request.ContentType = ContentType; 97 request.Accept = "application/x-www-form-urlencoded; charset=UTF-8"; 98 if (keys != null) 99 { 100 foreach (KeyValuePair<string, string> pair in keys) 101 { 102 request.Headers.Add(pair.Key, pair.Value); 103 } 104 } 105 if (_credentials != null) 106 { 107 request.Credentials = _credentials; 108 } 109 if ((parameters != null) && (parameters.Length > 0)) 110 { 111 byte[] bytes = charset.GetBytes(parameters.ToString()); 112 request.ContentLength = bytes.Length; 113 using (Stream stream2 = request.GetRequestStream()) 114 { 115 //body.CopyToAsync(stream2); 116 stream2.Write(bytes, 0, bytes.Length); 117 } 118 } 119 try 120 { 121 response = (HttpWebResponse) request.GetResponse(); 122 } 123 catch (WebException exception) 124 { 125 response = (HttpWebResponse) exception.Response; 126 } 127 Stream responseStream = response.GetResponseStream(); 128 StreamReader reader = new StreamReader(responseStream, Encoding.UTF8); 129 string str = reader.ReadToEnd(); 130 reader.Close(); 131 responseStream.Close(); 132 return str; 133 } 134 private static Dictionary<string, string> httpHeadParametersSet(string apiName, string version, string accessKey, string securityKey,Dictionary<string,string> requestdata) { 135 Dictionary<string, string> paramsDic = new Dictionary<string, string>(); 136 paramsDic.Add("_api_name", apiName); 137 paramsDic.Add("_api_version", version); 138 139 DateTime time = new DateTime(0x7b2, 1, 1, 0, 0, 0, DateTimeKind.Utc); 140 TimeSpan span = (TimeSpan)(DateTime.UtcNow - time); 141 paramsDic.Add("_api_timestamp", ((long)span.TotalMilliseconds).ToString()); 142 paramsDic.Add("_api_access_key", accessKey); 143 144 paramsDic.Add("_api_signature", SignUtil.sign(requestdata, securityKey)); 145 146 return paramsDic; 147 148 } 149 public static string HttpPOST(string url, string parameters, Dictionary<string, string> keys) 150 { 151 return Http(url, parameters, Encoding.GetEncoding("utf-8"), null, keys, "application/x-www-form-urlencoded", "POST"); 152 } 153 154 private static Dictionary<string, string> newParamsMap(Dictionary<string, string> paramsMap, string apiName, string version, string accessKey, string securityKey) 155 { 156 Dictionary<string, string> newParamsMap = new Dictionary<string, string>(); 157 if (paramsMap != null) 158 { 159 foreach (KeyValuePair<string, string> pair in paramsMap) 160 { 161 if (!newParamsMap.ContainsKey(pair.Key)) 162 { 163 newParamsMap[pair.Key] = pair.Value; 164 } 165 } 166 } 167 newParamsMap.Add("_api_access_key", accessKey); 168 newParamsMap.Add("_api_name", apiName); 169 170 171 172 DateTime time = new DateTime(0x7b2, 1, 1, 0, 0, 0, DateTimeKind.Utc); 173 TimeSpan span = (TimeSpan) (DateTime.UtcNow - time); 174 newParamsMap.Add("_api_timestamp", ((long) span.TotalMilliseconds).ToString()); 175 176 177 178 newParamsMap.Add("_api_version", version); 179 newParamsMap.Add("_api_signature", SignUtil.sign(newParamsMap, securityKey)); 180 return newParamsMap; 181 } 182 183 private static Dictionary<string, string> parseUrlParamsMap(string requestURL) 184 { 185 bool flag = requestURL.IndexOf("?") > -1; 186 Dictionary<string, string> dictionary = new Dictionary<string, string>(); 187 if (flag) 188 { 189 int index = requestURL.IndexOf("?"); 190 char[] separator = new char[] { '&' }; 191 string[] strArray = requestURL.Substring(index + 1).Split(separator); 192 foreach (string str2 in strArray) 193 { 194 index = str2.IndexOf("="); 195 if (index <= 0) 196 { 197 throw new Exception("bad request URL, url params error:" + requestURL); 198 } 199 dictionary.Add(str2.Substring(0, index), str2.Substring(index + 1)); 200 } 201 } 202 return dictionary; 203 } 204 205 private static string trimUrl(string requestURL) 206 { 207 int index = requestURL.IndexOf("?"); 208 string str = requestURL; 209 if (index >= 0) 210 { 211 str = requestURL.Substring(0, index); 212 Console.WriteLine("-- orignal url=" + requestURL); 213 Console.WriteLine("-- new url=" + str); 214 } 215 return str; 216 } 217 218 private static void validateParams(string apiName, string accessKey, string securityKey) 219 { 220 if (apiName == null) 221 { 222 throw new Exception("param apiName can not be null!"); 223 } 224 if ((accessKey != null) && (securityKey == null)) 225 { 226 throw new Exception("param securityKey can not be null for a given accessKey!"); 227 } 228 } 229 } 230 }
签名算法类
1 namespace CSBSDK.NET 2 { 3 using System; 4 using System.Collections.Generic; 5 using System.Linq; 6 using System.Runtime.CompilerServices; 7 using System.Security.Cryptography; 8 using System.Text; 9 10 public class SignUtil 11 { 12 public static string sign(Dictionary<string, string> newParamsMap, string secretKey) 13 { 14 Dictionary<string, string> dictionary = (from d in newParamsMap 15 16 select d).ToDictionary<KeyValuePair<string, string>, string, string>(k => k.Key, v => v.Value); 17 StringBuilder builder = new StringBuilder(); 18 foreach (KeyValuePair<string, string> pair in dictionary) 19 { 20 21 builder.Append(string.Format("{0}={1}&", pair.Key, pair.Value)); 22 } 23 string str = builder.ToString(); 24 if (str.EndsWith("&")) 25 { 26 str = str.Substring(0, str.Length - 1); 27 } 28 Console.WriteLine(str); 29 HMACSHA1 hmacsha = new HMACSHA1 { 30 Key = Encoding.UTF8.GetBytes(secretKey) 31 }; 32 byte[] bytes = Encoding.UTF8.GetBytes(str); 33 return Convert.ToBase64String(hmacsha.ComputeHash(bytes)); 34 } 35 36 37 } 38 }
测试控制台:
1 class Program 2 { 3 static void Main(string[] args) 4 { 5 var requesturl = "https://api-csb-broker.boe.com.cn:443/test"; 6 var apiname = "boe_hubtoecc_gr"; 7 var version = "1.0.0"; 8 9 var xd = new XmlDocument(); 10 xd.Load(@"d:\\GR-FL11IN0000082266.xml"); 11 var js = JsonConvert.SerializeXmlNode(xd, Newtonsoft.Json.Formatting.None, true); 12 13 14 var requestdata = new Dictionary<string, string>(); 15 requestdata.Add("MT_BOE_HUBTOECC_GR", js ); 16 var ak = "94717a0403804b039834a7cab929d4a4"; 17 var sk = "zJke7U3yGMG7kGQ9SfxfU/hzzBg="; 18 19 var result = CSBSDK.NET.HttpCaller.doPost(requesturl, apiname, version, requestdata, ak, sk); 20 Console.Write(result); 21 22 Console.ReadLine(); 23 24 25 } 26 }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix