你的位置:首页 > ASP.net教程

[ASP.net教程]WebApi系列~安全校验中的防篡改和防复用


回到目录

web api越来越火,因为它的跨平台,因为它的简单,因为它支持

防篡改

一般使用的方式就是把参数拼接,加上双方约定的“密钥”,加上你的当前项目AppKey,做一次MD5加密,这个过程生成的字符串我们一般称为密文,而对应的可见参数我们叫明文,其中明文和密文用于网络传输,而密钥存储在本地和服务器,不能进行传输!

防复用

一般请求,被重复的使用,也是正常的,就上面的方式进行加密,就无法解决防复用的问题,这时我们需要在客户端和服务端分别生成UTC的时间戳,这个UTC是防止你的客户端与服务端不在同一个时区,呵呵,然后把时间戳timestamp拼在密文里就可以了,至于防复用的有效性,我们可以自定义,当然大叔定义的是秒,即同一秒内,请求可以重复发送。

大叔API安全结构图

web api核心安全校验代码片断

代码供大家参考和学习,正式的项目可以根据自己公司的需要去设计

 /// <summary>  /// 功能:api数据安全性验证  /// 校验方式:ciphertext=md5(form键的值拼接+timestamp+passkey),服务端用接收到的表单数据与时间戳和自己的passkey进行md5生成,最后比较值是否一致  /// passkey为私钥,不用于网络传递,你可以将它与appKey进行关联,appKey用来传递,服务器根据appKey去数据库里取对应的passkey然后进行比较  /// 功能:请求唯一性,防伪造性  /// timestamp:UTC时间戳,不用于网络传递,在客户端调用服务器时,服务器也生成yyyyMMddhhmmss的时间戳,然后进行计算,看是否过期  /// </summary>  [AttributeUsage(AttributeTargets.Method)]  public class ApiValidateFilter : ActionFilterAttribute  {    public override void OnActionExecuting(System.Web.Http.Controllers.HttpActionContext actionContext)    {      #region 初始化      var context = (HttpContextBase)actionContext.Request.Properties["MS_HttpContext"];//获取传统context      var request = context.Request;//定义传统request对象      var paramStr = new StringBuilder();      var coll = new NameValueCollection();      if (request.HttpMethod.ToLower() == "get")        coll = request.QueryString;      else        coll = request.Form;      #endregion      #region 解析var config = CacheConfigFile.ConfigFactory.Instance.GetConfig<ApiValidateModelConfig>().ApiValidateModelList.FirstOrDefault(i => i.AppKey == coll["AppKey"]);      if (config == null)      {        actionContext.Response = new HttpResponseMessage(HttpStatusCode.Forbidden)        {          Content = new StringContent("AppKey不是合并的,请先去组织生成有效的Key", Encoding.GetEncoding("UTF-8"))        };        base.OnActionExecuting(actionContext);      }      if (config.ExpireDate < DateTime.Now)      {        actionContext.Response = new HttpResponseMessage(HttpStatusCode.Forbidden)        {          Content = new StringContent("AppKey不是合并的,密钥已过期", Encoding.GetEncoding("UTF-8"))        };        base.OnActionExecuting(actionContext);      }      #endregion      #region 验证算法      var keys = new List<string>();      foreach (string param in coll.Keys)      {        if (!string.IsNullOrEmpty(param))        {          keys.Add(param.ToLower());        }      }      keys.Sort();      foreach (string p in keys)      {        if (p != "ciphertext")        {          if (!string.IsNullOrEmpty(coll[p]))          {            paramStr.Append(coll[p]);          }        }      }      paramStr.Append(DateTime.Now.ToUniversalTime().ToString("yyyyMMddHHmmss"));      paramStr.Append(config.PassKey);      #endregion      if (Lind.DDD.Utils.Encryptor.Utility.EncryptString(paramStr.ToString(), Lind.DDD.Utils.Encryptor.Utility.EncryptorType.MD5)        != request["cipherText"])      {        actionContext.Response = new HttpResponseMessage(HttpStatusCode.Forbidden)        {          Content = new StringContent("验证失败,请求非法", Encoding.GetEncoding("UTF-8"))        };      }      base.OnActionExecuting(actionContext);    }  }

在上的配置项大叔把它存储到的

这个在大叔框架里经常被看到,呵呵。

回到目录