2023年6月20日发(作者:)
【签名验证】WEBAPI增加⽅法签名验证(包含⽂件上传功能)1. ⽬前需要将本地⽂件通过 WEB API 上传到服务器上,进⾏后续的存档与读取,上个节点通过token 验证的⽅式不太安全,因此选择本次内容2. 创建WEB API 项⽬3. 新建⽂件夹 Filters ,并新建类:4. 在类中编写相关验证规范using ;using System;using c;using uration;using ;using ;using ;using ;using ;using ;using llers;namespace webapitokensign{ public class OAuthAuthorizeAttribute : AuthorizeAttribute { protected string Msg { get; private set; } protected override void HandleUnauthorizedRequest(HttpActionContext actionContext) { se = new HttpResponseMessage() { StatusCode = orized,
Content = new StringContent("错误信息", oding("UTF-8"), "application/json"), }; } protected override bool IsAuthorized(HttpActionContext actionContext) { var clientkey = ;//客户Key var clientIp = ;//客户端IP var timestamp = ;//时间戳 var nonce = ;//随机数 var signature = ;//签名 var action = ;//⽅法 #region 获取签名参数 if (ns("clientkey")) { clientkey = ode(ues("clientkey").FirstOrDefault()); }
if (ns("timestamp")) { timestamp = ode(ues("timestamp").FirstOrDefault()); } if (ns("nonce")) { nonce = ode(ues("nonce").FirstOrDefault()); } if (ns("signature")) { signature = ode(ues("signature").FirstOrDefault()); } } if (ns("action")) { action = ode(ues("action").FirstOrDefault()); } if (OrEmpty(clientkey) || OrEmpty(timestamp) || OrEmpty(nonce) || OrEmpty(signature)) { Msg = "签名验证参数缺失,验证失败!"; //("【" + clientkey + "】签名验证参数缺失,验证失败"); return false; } #endregion #region 验证ClientKey var oauthConfig = clientkey; if (oauthConfig == null) { Msg = "签名参数ClientKey值不存在,验证失败!"; return false; } #endregion
#region 判断timespan是否有效 double requestTimeStamp = 0;//请求时间戳 if (!se(timestamp, out requestTimeStamp)) { Msg = "签名时间戳不合法,验证失败!"; //("【" + clientkey + "】签名时间戳不合法,验证失败。当前签名时间戳:" + timestamp); return false; } var requestExpireTime = 60;// tings["RequestExpireTime"];//请求签名过期时间 double requestExpireTimeStamp = 32(requestExpireTime) * 1000; double currentTimeStamp = ( - new DateTime(1970, 1, 1, 0, 0, 0, 0)).TotalMilliseconds;//当前时间戳
if ((currentTimeStamp - requestTimeStamp) > requestExpireTimeStamp) { Msg = "请求签名过期,验证失败!"; //("【" + clientkey + "】请求签名过期,验证失败"); return false; } #endregion #region 验证签名 var requestData = ; var method = r();//请求⽅式 if (("post")) {//Post请求 Stream stream = tream; StreamReader streamReader = new StreamReader(stream); requestData = End(); if (action == "upload") { requestData = ""; } } if (("get")) {//Get请求 //取出所有get参数 //取出所有get参数 IDictionary parameters = new Dictionary(); for (int f = 0; f < ; f++) { string key = [f]; (key, tring[key]); } //把字典按Key的字母顺序排序 IDictionary sortedParams = new SortedDictionary(parameters); IEnumerator> dem = merator(); //把所有参数名和参数值串在⼀起 StringBuilder query = new StringBuilder(); while (xt()) { string key = ; string value = ; if (!OrEmpty(key)) { (key).Append(value); } } requestData = ng(); } if (!ValidSignature(timestamp, nonce, clientkey, requestData, signature)) { Msg = "签名验证失败!"; //("【" + clientkey + "】签名验证失败,数据:" + timestamp + "|" + nonce + "|" + clientkey + "|" + requestData + "|" + signature); return false; } #endregion
return true; } /// ///
验证签名 /// /// 时间戳 /// 随机数 /// /// /// 数据 /// 签名 /// private bool ValidSignature(string timeStamp, string nonce, string clientKey, string data, string signature) { var hash = (); //拼接签名数据 var signStr = timeStamp + nonce + clientKey + data; //将字符串中字符按升序排序 var sortStr = (y(c => c)); var bytes = es(sortStr); //使⽤MD5加密 var md5Val = eHash(bytes); //把⼆进制转化为⼤写的⼗六进制 StringBuilder result = new StringBuilder(); foreach (var c in md5Val) { (ng("X2")); (ng("X2")); } return ng().ToUpper() == signature; } }}5. 在API 接⼝上增加规则 [OAuthAuthorize] 即可6. 请求过程中,需要传递当前需要的参数到head当中7. 全局设置在 中增加8. (new uthorizeAttribute());验证逻辑从头信息中获取到 timeStamp(时间戳), nonce(随机数), clientKey(密钥), clientSecret(客户端匹配密钥),参数,signature(由 timeStamp, nonce, clientKey, clientSecret,参数 组成并⽣成加密字符串) #region 获取签名参数 if (ns("clientkey")) { clientkey = ode(ues("clientkey").FirstOrDefault()); } clientIp = GetIPAddress(); if (ns("timestamp")) { timestamp = ode(ues("timestamp").FirstOrDefault()); } if (ns("nonce")) { nonce = ode(ues("nonce").FirstOrDefault()); } if (ns("signature")) { signature = ode(ues("signature").FirstOrDefault()); } if (ns("action")) { action = ode(ues("action").FirstOrDefault()); } if (OrEmpty(clientkey) || OrEmpty(timestamp) || OrEmpty(nonce) || OrEmpty(signature)) { Msg = "签名验证参数缺失,验证失败!"; //("【" + clientkey + "】签名验证参数缺失,验证失败"); return false; } #endregion验证时间戳,是否在规定的时间期限之内当前时间减去初始化时间的值减去timestamp 的值是否⼩于配置的时间 var requestExpireTime = 60;// tings["RequestExpireTime"];//请求签名过期时间 double requestExpireTimeStamp = 32(requestExpireTime) * 1000; double currentTimeStamp = ( - new DateTime(1970, 1, 1, 0, 0, 0, 0)).TotalMilliseconds;//当前时间戳
if ((currentTimeStamp - requestTimeStamp) > requestExpireTimeStamp) { Msg = "请求签名过期,验证失败!"; //("【" + clientkey + "】请求签名过期,验证失败"); return false; }验证密钥,通过 clientkey 获取 服务端数据配置clientSecret,判断是否存在验证IP地址 ,并从服务端中获取是否存在/// ///
获取IP地址/// /// private string GetIPAddress(){ var userIP = ; HttpRequest Request = t; if (Variables["HTTP_X_FORWARDED_FOR"] != "") { userIP = Variables["REMOTE_ADDR"]; } else { userIP = Variables["HTTP_X_FORWARDED_FOR"]; } if (userIP == null || userIP == "") { userIP = stAddress; } return userIP;}验证签名,判断请求的发送⽅法,区分post ,get 。var method = r();//请求⽅式若post ,从 tream 获取参数,转成字符串 if (("post")) {//Post请求 Stream stream = tream; StreamReader streamReader = new StreamReader(stream); requestData = End(); if (action == "upload") { requestData = ""; } }若get ,从 tring 获取参数,并通过字典参数key 进⾏排序转成字符串if (("get")) {//Get请求 //取出所有get参数 IDictionary parameters = new Dictionary(); for (int f = 0; f < ; f++) { string key = [f]; (key, tring[key]); } //把字典按Key的字母顺序排序 IDictionary sortedParams = new SortedDictionary(parameters); IEnumerator> dem = merator(); //把所有参数名和参数值串在⼀起 StringBuilder query = new StringBuilder(); while (xt()) { string key = ; string value = ; if (!OrEmpty(key)) { (key).Append(value); } } requestData = ng(); }将签名再次进⾏组成并⽣成加密字符串与signature 的值进⾏验证,若相同,则签名验证通过/// ///
验证签名/// /// 时间戳/// 随机数/// /// /// 数据/// 签名/// private bool ValidSignature(string timeStamp, string nonce, string clientKey, string clientSecret, string data, string signature){ var hash = (); //拼接签名数据 var signStr = timeStamp + nonce + clientKey + clientSecret + data; //将字符串中字符按升序排序 var sortStr = (y(c => c)); var bytes = es(sortStr); //使⽤MD5加密 var md5Val = eHash(bytes); //把⼆进制转化为⼤写的⼗六进制 StringBuilder result = new StringBuilder(); foreach (var c in md5Val) { (ng("X2")); } return ng().ToUpper() == signature;}验证scope (略)调⽤: using (HttpClient client = new HttpClient()) { var content = new MultipartFormDataContent(); //添加字符串参数,参数名为qq //(new StringContent("123456"), "qq"); string path = file;//e(tDirectory, ""); //添加⽂件参数,参数名为files,⽂件名为 (new ByteArrayContent(lBytes(path)), "file", ""); //(new StringContent("123456"), "qq"); string timeStamp = eStamp(); var nonce = dom(); var dataStr = izeObject(data); ("clientkey", clientKey); ("timestamp", timeStamp); ("nonce", nonce); ("action", "upload"); ("signature", nature(timeStamp, nonce, clientKey, clientSecret, "")); var requestUri = "localhost:60298/api/values/import"; var result = ync(requestUri, content).StringAsync().Result; ine(result); }待续。。。
2023年6月20日发(作者:)
【签名验证】WEBAPI增加⽅法签名验证(包含⽂件上传功能)1. ⽬前需要将本地⽂件通过 WEB API 上传到服务器上,进⾏后续的存档与读取,上个节点通过token 验证的⽅式不太安全,因此选择本次内容2. 创建WEB API 项⽬3. 新建⽂件夹 Filters ,并新建类:4. 在类中编写相关验证规范using ;using System;using c;using uration;using ;using ;using ;using ;using ;using ;using llers;namespace webapitokensign{ public class OAuthAuthorizeAttribute : AuthorizeAttribute { protected string Msg { get; private set; } protected override void HandleUnauthorizedRequest(HttpActionContext actionContext) { se = new HttpResponseMessage() { StatusCode = orized,
Content = new StringContent("错误信息", oding("UTF-8"), "application/json"), }; } protected override bool IsAuthorized(HttpActionContext actionContext) { var clientkey = ;//客户Key var clientIp = ;//客户端IP var timestamp = ;//时间戳 var nonce = ;//随机数 var signature = ;//签名 var action = ;//⽅法 #region 获取签名参数 if (ns("clientkey")) { clientkey = ode(ues("clientkey").FirstOrDefault()); }
if (ns("timestamp")) { timestamp = ode(ues("timestamp").FirstOrDefault()); } if (ns("nonce")) { nonce = ode(ues("nonce").FirstOrDefault()); } if (ns("signature")) { signature = ode(ues("signature").FirstOrDefault()); } } if (ns("action")) { action = ode(ues("action").FirstOrDefault()); } if (OrEmpty(clientkey) || OrEmpty(timestamp) || OrEmpty(nonce) || OrEmpty(signature)) { Msg = "签名验证参数缺失,验证失败!"; //("【" + clientkey + "】签名验证参数缺失,验证失败"); return false; } #endregion #region 验证ClientKey var oauthConfig = clientkey; if (oauthConfig == null) { Msg = "签名参数ClientKey值不存在,验证失败!"; return false; } #endregion
#region 判断timespan是否有效 double requestTimeStamp = 0;//请求时间戳 if (!se(timestamp, out requestTimeStamp)) { Msg = "签名时间戳不合法,验证失败!"; //("【" + clientkey + "】签名时间戳不合法,验证失败。当前签名时间戳:" + timestamp); return false; } var requestExpireTime = 60;// tings["RequestExpireTime"];//请求签名过期时间 double requestExpireTimeStamp = 32(requestExpireTime) * 1000; double currentTimeStamp = ( - new DateTime(1970, 1, 1, 0, 0, 0, 0)).TotalMilliseconds;//当前时间戳
if ((currentTimeStamp - requestTimeStamp) > requestExpireTimeStamp) { Msg = "请求签名过期,验证失败!"; //("【" + clientkey + "】请求签名过期,验证失败"); return false; } #endregion #region 验证签名 var requestData = ; var method = r();//请求⽅式 if (("post")) {//Post请求 Stream stream = tream; StreamReader streamReader = new StreamReader(stream); requestData = End(); if (action == "upload") { requestData = ""; } } if (("get")) {//Get请求 //取出所有get参数 //取出所有get参数 IDictionary parameters = new Dictionary(); for (int f = 0; f < ; f++) { string key = [f]; (key, tring[key]); } //把字典按Key的字母顺序排序 IDictionary sortedParams = new SortedDictionary(parameters); IEnumerator> dem = merator(); //把所有参数名和参数值串在⼀起 StringBuilder query = new StringBuilder(); while (xt()) { string key = ; string value = ; if (!OrEmpty(key)) { (key).Append(value); } } requestData = ng(); } if (!ValidSignature(timestamp, nonce, clientkey, requestData, signature)) { Msg = "签名验证失败!"; //("【" + clientkey + "】签名验证失败,数据:" + timestamp + "|" + nonce + "|" + clientkey + "|" + requestData + "|" + signature); return false; } #endregion
return true; } /// ///
验证签名 /// /// 时间戳 /// 随机数 /// /// /// 数据 /// 签名 /// private bool ValidSignature(string timeStamp, string nonce, string clientKey, string data, string signature) { var hash = (); //拼接签名数据 var signStr = timeStamp + nonce + clientKey + data; //将字符串中字符按升序排序 var sortStr = (y(c => c)); var bytes = es(sortStr); //使⽤MD5加密 var md5Val = eHash(bytes); //把⼆进制转化为⼤写的⼗六进制 StringBuilder result = new StringBuilder(); foreach (var c in md5Val) { (ng("X2")); (ng("X2")); } return ng().ToUpper() == signature; } }}5. 在API 接⼝上增加规则 [OAuthAuthorize] 即可6. 请求过程中,需要传递当前需要的参数到head当中7. 全局设置在 中增加8. (new uthorizeAttribute());验证逻辑从头信息中获取到 timeStamp(时间戳), nonce(随机数), clientKey(密钥), clientSecret(客户端匹配密钥),参数,signature(由 timeStamp, nonce, clientKey, clientSecret,参数 组成并⽣成加密字符串) #region 获取签名参数 if (ns("clientkey")) { clientkey = ode(ues("clientkey").FirstOrDefault()); } clientIp = GetIPAddress(); if (ns("timestamp")) { timestamp = ode(ues("timestamp").FirstOrDefault()); } if (ns("nonce")) { nonce = ode(ues("nonce").FirstOrDefault()); } if (ns("signature")) { signature = ode(ues("signature").FirstOrDefault()); } if (ns("action")) { action = ode(ues("action").FirstOrDefault()); } if (OrEmpty(clientkey) || OrEmpty(timestamp) || OrEmpty(nonce) || OrEmpty(signature)) { Msg = "签名验证参数缺失,验证失败!"; //("【" + clientkey + "】签名验证参数缺失,验证失败"); return false; } #endregion验证时间戳,是否在规定的时间期限之内当前时间减去初始化时间的值减去timestamp 的值是否⼩于配置的时间 var requestExpireTime = 60;// tings["RequestExpireTime"];//请求签名过期时间 double requestExpireTimeStamp = 32(requestExpireTime) * 1000; double currentTimeStamp = ( - new DateTime(1970, 1, 1, 0, 0, 0, 0)).TotalMilliseconds;//当前时间戳
if ((currentTimeStamp - requestTimeStamp) > requestExpireTimeStamp) { Msg = "请求签名过期,验证失败!"; //("【" + clientkey + "】请求签名过期,验证失败"); return false; }验证密钥,通过 clientkey 获取 服务端数据配置clientSecret,判断是否存在验证IP地址 ,并从服务端中获取是否存在/// ///
获取IP地址/// /// private string GetIPAddress(){ var userIP = ; HttpRequest Request = t; if (Variables["HTTP_X_FORWARDED_FOR"] != "") { userIP = Variables["REMOTE_ADDR"]; } else { userIP = Variables["HTTP_X_FORWARDED_FOR"]; } if (userIP == null || userIP == "") { userIP = stAddress; } return userIP;}验证签名,判断请求的发送⽅法,区分post ,get 。var method = r();//请求⽅式若post ,从 tream 获取参数,转成字符串 if (("post")) {//Post请求 Stream stream = tream; StreamReader streamReader = new StreamReader(stream); requestData = End(); if (action == "upload") { requestData = ""; } }若get ,从 tring 获取参数,并通过字典参数key 进⾏排序转成字符串if (("get")) {//Get请求 //取出所有get参数 IDictionary parameters = new Dictionary(); for (int f = 0; f < ; f++) { string key = [f]; (key, tring[key]); } //把字典按Key的字母顺序排序 IDictionary sortedParams = new SortedDictionary(parameters); IEnumerator> dem = merator(); //把所有参数名和参数值串在⼀起 StringBuilder query = new StringBuilder(); while (xt()) { string key = ; string value = ; if (!OrEmpty(key)) { (key).Append(value); } } requestData = ng(); }将签名再次进⾏组成并⽣成加密字符串与signature 的值进⾏验证,若相同,则签名验证通过/// ///
验证签名/// /// 时间戳/// 随机数/// /// /// 数据/// 签名/// private bool ValidSignature(string timeStamp, string nonce, string clientKey, string clientSecret, string data, string signature){ var hash = (); //拼接签名数据 var signStr = timeStamp + nonce + clientKey + clientSecret + data; //将字符串中字符按升序排序 var sortStr = (y(c => c)); var bytes = es(sortStr); //使⽤MD5加密 var md5Val = eHash(bytes); //把⼆进制转化为⼤写的⼗六进制 StringBuilder result = new StringBuilder(); foreach (var c in md5Val) { (ng("X2")); } return ng().ToUpper() == signature;}验证scope (略)调⽤: using (HttpClient client = new HttpClient()) { var content = new MultipartFormDataContent(); //添加字符串参数,参数名为qq //(new StringContent("123456"), "qq"); string path = file;//e(tDirectory, ""); //添加⽂件参数,参数名为files,⽂件名为 (new ByteArrayContent(lBytes(path)), "file", ""); //(new StringContent("123456"), "qq"); string timeStamp = eStamp(); var nonce = dom(); var dataStr = izeObject(data); ("clientkey", clientKey); ("timestamp", timeStamp); ("nonce", nonce); ("action", "upload"); ("signature", nature(timeStamp, nonce, clientKey, clientSecret, "")); var requestUri = "localhost:60298/api/values/import"; var result = ync(requestUri, content).StringAsync().Result; ine(result); }待续。。。
发布评论