• web api接口安全设计(签名校验方式)


    最原始接口:public string GetProjectInfo(string latest_update_time);

    修改后接口:public string GetProjectInfo(string latest_update_time, string appKey, string timeStamp, string nonce, string signature);

    添加参数:

    appKey 接口Key
    appSecret 接口密钥
    timeStamp 时间戳 毫秒
    nonceStr 随机字符串
    signature 加密字符串

    解决三个接口安全问题:

    1.保证参数不被篡改

    2.保证访问的合法性

    3.保证请求的唯一性,防止暴力访问

    签名校验的原理就是appSecret 只有你知我知,通过加入appSecret 加密生成的签名无法破解,这样就可到达确保参数不被修改,因为服务端会通过相同的算法生成签名,如果和传过来的签名不一样则代表参数发生了改表

    签名算法 比如:signature =MD5(appKey +timeStamp +nonceStr +appSecret )

    时间戳+随机字符串就可以防止接口被同一个请求重复调用

    服务端设置一个时效时间,比如十分钟,十分钟内请求合理,在判断nonceStr 随机字符串在服务端是否有缓存,有的话也代表请求失效

    接口定义:

     public string GetProjectInfo(string latest_update_time, string appKey, string timeStamp, string nonce, string signature);

    /// <summary>
        /// 验证
        /// </summary>
        /// <param name="latest_update_time"></param>
        /// <param name="appKey"></param>
        /// <param name="timeStamp"></param>
        /// <param name="nonce"></param>
        /// <param name="signature"></param>
        public void Verification(string latest_update_time, string appKey, string timeStamp, string nonce, string signature)
        {
            try
            {
                DateTime update_time = DateTime.MinValue; string appSecret = "";
                //更新时间
                if (StringUtil.isNotNullOrBlank(latest_update_time))
                {
                    if (!DateTime.TryParse(latest_update_time, out update_time))
                    {
                        throw new Exception("参数latest_update_time格式不正确");
                    }
                }
                else
                {
                    throw new Exception("参数latest_update_time不能为空");
                }
                //appKey
                if (StringUtil.isNotNullOrBlank(appKey))
                {
                    if (appDic.ContainsKey(appKey))
                    {
                        appSecret = appDic[appKey];
                    }
                    else
                    {
                        throw new Exception("参数appKey不合法");
                    }
                }
                else
                {
                    throw new Exception("参数appKey不能为空");
                }
                //timeStamp时间戳
                if (StringUtil.isNotNullOrBlank(timeStamp))
                {
                    long currentTimeStamp = Convert.ToInt64(GetTimeStamp());
                    //有效期60分钟
                    if (Math.Abs(currentTimeStamp - Convert.ToInt64(timeStamp)) > (60 * 60 * 1000))
                    {
                        throw new Exception("参数timeStamp已过期");
                    }
                }
                else
                {
                    throw new Exception("参数timeStamp不能为空");
                }
                //随机字符串
                if (StringUtil.isNotNullOrBlank(nonce))
                {
                    if (CacheHelper.GetCache(nonce) == null)
                    {
                        CacheHelper.SetCache(nonce, timeStamp, 10 * 60);
                    }
                    else
                    {
                        throw new Exception("参数nonce已使用");
                    }
                }
                else
                {
                    throw new Exception("参数nonce不能为空");
                }
                //signature签名
                if (StringUtil.isNotNullOrBlank(signature))
                {
                    string signTempStr = appSecret + latest_update_time + appKey + timeStamp + nonce + appSecret;
                    string signResult = GenerateMD5(signTempStr);
                    if (signature != signResult)
                    {
                        throw new Exception("签名验证失败");
                    }
                }
                else
                {
                    throw new Exception("参数signature不能为空");
                }
            }
            catch (Exception)
            {
    
                throw;
            }
        }
        /// <summary>
        /// 获取时间戳 毫秒
        /// </summary>
        /// <returns></returns>
        public static string GetTimeStamp()
        {
            TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0);
            return Convert.ToInt64(ts.TotalMilliseconds).ToString();
        }
        /// <summary>
        /// Md5加密 32位小写
        /// </summary>
        /// <param name="txt"></param>
        /// <returns></returns>
        public static string GenerateMD5(string str)
        {
            using (MD5 mi = MD5.Create())
            {
                byte[] buffer = Encoding.Default.GetBytes(str);
                //开始加密
                byte[] newBuffer = mi.ComputeHash(buffer);
                StringBuilder sb = new StringBuilder();
                for (int i = 0; i < newBuffer.Length; i++)
                {
                    sb.Append(newBuffer[i].ToString("x2"));
                }
                return sb.ToString();
            }
        }
  • 相关阅读:
    Javascript设计模式理论与实战:单例模式
    详解CSS盒模型
    linux添加计划任务
    python删除目录下七天前创建的文件
    centos上源码安装clang 3.8
    使用postman发送数据并构建collections执行测试
    python多线程实现同时执行两个while循环
    使用Python写Windows Service服务程序
    用Pyinstaller打包发布exe应用
    使用Jmeter监测服务器cpu、内存等性能
  • 原文地址:https://www.cnblogs.com/LDJW/p/16087422.html
Copyright © 2020-2023  润新知