WebApi系列~安全校验中的防篡改和防复用

回到目录

web api越来越火,因为它的跨平台,因为它的简单,因为它支持xml,json等流行的数据协议,我们在开发基于面向服务的API时,有个问题一直在困扰着我们,那就是数据的安全,请求的安全,一般所说的安全也无非就是请求的防篡改和请求的防复用,例如,你向API发一个查询用户账户的请求,在这个过程中,你可能要传递用户ID,用户所在项目ID等,而现在拦截工具如此盛行,很容易就可以把它的请求拦截,然后篡改,再转发,这样你的API就是不安全的,而对于订单,账户模块这种糟糕的API设计更是致命的,可能引起的损失是不可预计的,是灾难性的,拍拍脑子想想就知道,你向项目提现10元,我把请求拦截把10改成100000,那么这个将是一个灾难!

防篡改

一般使用的方式就是把参数拼接,加上双方约定的“密钥”,加上你的当前项目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 解析XML配置文件
            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);
        }
    }

在上的配置项大叔把它存储到的XML里,使用的是大叔自己封装的XML缓存组件CacheConfigFile,文件第一次访问会加载到内存,下次使用直接从内存返回,而当文件修改后,文件的最后更新时间发生变化,这时缓存过期,在生产缓存时,还是采用了单例模式,

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

回到目录

时间: 2024-10-09 04:48:55

WebApi系列~安全校验中的防篡改和防复用的相关文章

WebApi系列~实际项目中如何使用HttpClient向web api发异步Get和Post请求并且参数于具体实体类型

本讲比较实际,在WEB端有一个Index和Create方法,用来从web api显示实体列表数据和向api插入实体对象,这就是以往的网站,只不过是把数据持久化过程放到了web pai上面,它的优势不用说,就是跨平台,跨语言,这其实是restFul的功功,一切通讯都变得那个简易,清晰!你再也不用引用程序集了... 先看一下实体的具体效果 我们看到如图,它们在取数据和插数据的时间,走的都是restful标准,都是通过web api实现的,当然,对于通讯来说,要求你的实体必须是可序列化的,这是正常的,

WebApi系列~目录

回到占占推荐博客索引 写了这个系列的文章不少了,也应该为大家写个目录了,最近很刮了很多SOA的风,很多企业都将自己的系统进行分割,通常是按模块进行拆分,为这个模块提供统一的接口提供业务服务,这不紧可以提高代码重用,也更好了扩展了其它服务,如为第三方提供一些数据,也可以通过这种soa模式来实现. WebApi系列~目录 WebApi系列~基于RESTful标准的Web Api (2014-02-19 13:30) WebApi系列~在WebApi中实现Cors访问 (2014-02-20 10:3

WebAPI 用户认证防篡改实现(二)AbsBaseAuthenticationAttribute

WebAPI的用户身份认证与MVC一样都是通过Attribute进行验证,此处定义了一个抽象基类,子类需要实现根据合作号获取合作用户信息的抽象方法 AbsBaseAuthenticationAttribute using System; using System.Web; using System.Collections.Specialized; using System.Net; using System.Net.Http; using System.Text.RegularExpressio

JavaScript中的防篡改对象

由于JavaScript共享的特性,任何对象都可以被放在同一环境下运行的代码修改. 例如: var person = {name:"caibin'} person.age = 21; 即使第一行定义了完整的person对象,那么第二行代码仍然可以对其添加属性,删除属性等. 我们有三个方法可以防止你做出这些行为. 一.不可扩展对象: 先来看person本身的扩展性: Object.isExtensible(person); // true 接下来执行: Object.preventExtensio

WebAPI 用户认证防篡改实现(一)MD5签名获取

在开始前先说下防篡改机制的原理,如果已经接触过支付宝的可以跳过此部分 防篡改,顾名思义就是防止有人恶意篡改请求数据以达到恶意攻击的目的,那要怎么才能实现这样的目的呢?其实很简单,将要请求的数据加上合作号.合作Key按规则组织成一个字符串,获取对应的MD5摘要,然后将该摘要及合作号同时作为请求的一部分一起传递(合作Key禁止传递) 下面进行举例: 假定需要进行签名的参数如下(以json格式举例): {'partner': '3122131212','orderNo':'1234567'} 对数组里

使用数字签名实现数据库记录防篡改(Java实现)

本文大纲 一.提出问题 二.数字签名 三.实现步骤 四.参考代码 五.后记 六.参考资料 一.提出问题 最近在做一个项目,需要对一个现成的产品的数据库进行操作,增加额外的功能.为此,需要对该产品对数据库有什么操作进行研究(至于怎么监控一个产品的操作会引发什么数据库操作,以后会详细解说).本来已经对数据库的操作了如指掌的,无意中发现数据库表里的每条记录都会有这样一个字段: 这感觉不妙了,字段名叫signature,顾名思义,就是签名的意思呀.难道数据库表中的每条记录都会有签名?也就是说如果我不能正

政府网站防篡改解决方案

政府网站防篡改解决方案        互联网的出现,被誉为 20 世纪最伟大的发明,它彻底改变了人们传统的生活方式,对现代社会产生了巨大影响.政府网站已成为政府电子政务的数字门户,是对外宣传国家政策法规的手段,是与社会大众交互.向社会大众提供服务和展现国家民主政治的重要窗口.随着网站数量不断增加,与之相对应的是网站受攻击的情况也越来越多.网站被攻击的各类情况中,网站页面被篡改事件给政府带来的影响尤其恶劣,影响面最广.尤其是含有政治攻击色彩的篡改,会对政府形象造成严重损害. 2006 年 3 月

[Asp.net MVC]Asp.net MVC5系列——在模型中添加验证规则

目录 概述 在模型中添加验证规则 自定义验证规则 伙伴类的使用 总结 系列文章 [Asp.net MVC]Asp.net MVC5系列——第一个项目 [Asp.net MVC]Asp.net MVC5系列——添加视图 [Asp.net MVC]Asp.net MVC5系列——添加模型 [Asp.net MVC]Asp.net MVC5系列——从控制器访问模型中的数据 [Asp.net MVC]Asp.net MVC5系列——添加数据 概述 上篇文章中介绍了添加数据,在提交表单的数据的时候,我们需

aip接口中对url参数md5加密防篡改的原理

目前网上所有开放api的网站中,数据的调用都是采用同一种方式,即: http:www.xxx.com/aa=1&bb=2...,原后对这些参数按字典顺序排序后进行md5加密,将md5加密串与接口方提供的 key接在参数后面提交,如http:www.xxx.com/aa=1&bb=2&sg=md5(...)& key=3432423,服务器端把这些参数接收后以同样的方式生成md5与提交的sg参数核对是否一致,以达到防止篡改与验证合法性的目的. 我现在的疑问是,既然参数可以被篡