web教程:WebAPI 安全性 使用TOKEN+签名验证(下)

  //根据请求类型拼接参数

  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 parameters = new Dictionary();

  for (int f = 0; f < form.Count; f++)

  {

  string key = form.Keys[f];

  parameters.Add(key, form[key]);

  }

  // 第二步:把字典按Key的字母顺序排序

  IDictionary sortedParams = new SortedDictionary(parameters);

  IEnumerator> 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

  WebAPI 安全性 使用TOKEN+签名验证(下)_安全性

  2.请求头添加timespan,staffid,nonce,signature字段

  WebAPI 安全性 使用TOKEN+签名验证(下)_安全性_02

  3.如图当data里面的值为id1namewahaha的时候请求头中的signature和服务器端计算出来的result的值是完全一样的,当我将data修改为id1namewahaha1之后,服务器端计算出来的签名result和请求头中提交的signature就不相同了,就表示为不合法的请求了

  WebAPI 安全性 使用TOKEN+签名验证(下)_web_03

  4.不合法的请求就会被识别为请求参数已被修改

  WebAPI 安全性 使用TOKEN+签名验证(下)_安全性_04

  post请求:

  1.post对象序列化为json字符串后提交到后台,后台返回相应产品信息

  WebAPI 安全性 使用TOKEN+签名验证(下)_API_05

  2.后台获取请求的参数信息

  WebAPI 安全性 使用TOKEN+签名验证(下)_安全性_06

  3.判断签名是否成功,第一次请求签名参数signature和服务器端计算result完全相同, 然后当把请求参数中count的数量从10改成100之后服务器端计算的result和请求签名参数signature不同,所以请求不合法,是非法请求,同理如果其他任何参数被修改最后计算的结果都会和签名参数不同,请求同样识别为不合法请求

  WebAPI 安全性 使用TOKEN+签名验证(下)_安全性_07

  总结:

  通过上面的案例,我们可以看出,安全的关键在于参与签名的TOKEN,整个过程中TOKEN是不参与通信的,所以只要保证TOKEN不泄露,请求就不会被伪造。

  然后我们通过timestamp时间戳用来验证请求是否过期,这样就算被人拿走完整的请求链接也是无效的。

  Sign签名的方式能够在一定程度上防止信息被篡改和伪造,保障通信的安全