//根據請求型別拼接引數
NameValueCollection form = HttpContext.Current.Request.QueryString;
string data = string.Empty;
switch (method)
{
case "POST":
Stream stream = HttpContext.Current.Request.InputStream;
string responseJson = string.Empty;
StreamReader streamReader = new StreamReader(stream);
data = streamReader.ReadToEnd();
break;
case "GET":
//第一步:取出所有get引數
IDictionary<string, string> parameters = new Dictionary<string, string>();
for (int f = 0; f < form.Count; f++)
{
string key = form.Keys[f];
parameters.Add(key, form[key]);
}
// 第二步:把字典按Key的字母順序排序
IDictionary<string, string> sortedParams = new SortedDictionary<string, string>(parameters);
IEnumerator<KeyValuePair<string, string>> dem = sortedParams.GetEnumerator();
// 第三步:把所有引數名和引數值串在一起
StringBuilder query = new StringBuilder();
while (dem.MoveNext())
{
string key = dem.Current.Key;
string value = dem.Current.Value;
if (!string.IsNullOrEmpty(key))
{
query.Append(key).Append(value);
}
}
data = query.ToString();
break;
default:
resultMsg = new ResultMsg();
resultMsg.StatusCode = (int)StatusCodeEnum.HttpMehtodError;
resultMsg.Info = StatusCodeEnum.HttpMehtodError.GetEnumText();
resultMsg.Data = "";
actionContext.Response = HttpResponseExtension.toJson(JsonConvert.SerializeObject(resultMsg));
base.OnActionExecuting(actionContext);
return;
}
bool result = SignExtension.Validate(timestamp, nonce, id, signtoken,data, signature);
if (!result)
{
resultMsg = new ResultMsg();
resultMsg.StatusCode = (int)StatusCodeEnum.HttpRequestError;
resultMsg.Info = StatusCodeEnum.HttpRequestError.GetEnumText();
resultMsg.Data = "";
actionContext.Response = HttpResponseExtension.toJson(JsonConvert.SerializeObject(resultMsg));
base.OnActionExecuting(actionContext);
return;
}
else
{
base.OnActionExecuting(actionContext);
}
}
public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
{
base.OnActionExecuted(actionExecutedContext);
}
}
然後我們進行測試,檢驗api請求的合法性
Get請求:
1.獲取產品資料,傳遞引數id=1,name="wahaha" ,完整請求為http://localhost:14826/api/product/getproduct?id=1&name=wahaha
2.請求頭新增timespan,staffid,nonce,signature欄位
3.如圖當data裡面的值為id1namewahaha的時候請求頭中的signature和伺服器端計算出來的result的值是完全一樣的,當我將data修改為id1namewahaha1之後,伺服器端計算出來的簽名result和請求頭中提交的signature就不相同了,就表示為不合法的請求了
4.不合法的請求就會被識別為請求引數已被修改
合法的請求則會返回對應的商品資訊
post請求:
1.post物件序列化為json字串後提交到後臺,後臺返回相應產品資訊
2.後臺獲取請求的引數資訊
3.判斷簽名是否成功,第一次請求籤名引數signature和伺服器端計算result完全相同, 然後當把請求引數中count的數量從10改成100之後伺服器端計算的result和請求籤名引數signature不同,所以請求不合法,是非法請求,同理如果其他任何引數被修改最後計算的結果都會和簽名引數不同,請求同樣識別為不合法請求
總結:
通過上面的案例,我們可以看出,安全的關鍵在於參與簽名的TOKEN,整個過程中TOKEN是不參與通訊的,所以只要保證TOKEN不洩露,請求就不會被偽造。
然後我們通過timestamp時間戳用來驗證請求是否過期,這樣就算被人拿走完整的請求連結也是無效的。
Sign簽名的方式能夠在一定程度上防止資訊被篡改和偽造,保障通訊的安全
原始碼地址:https://github.com/13138899620/TokenSign