Web API系列(二)接口安全和参数校验

  以前简单介绍过web api 的设计,但是还是有很多朋友问我,如何合理的设计和实现web api。比如,接口安全,异常处理,统一数据返回等问题。所以有必要系统的总结总结 web api 的设计和实现。由于前面已经介绍过web api 的参数和返回格式的设计,《Web API系列(一)设计经验与总结》。这次,就来讲讲接口安全。

 

  由于Web API是基于互联网的应用,因此安全性要远比在本地访问数据库的要严格的多,一般通用的做法,是采用几步来保证接口和数据安全:

  1.首先一个是基于CA证书的HTTPS进行数据传输,防止数据被窃听;

  2.然后是采用参数加密签名方式传递,对传递的参数,增加一个加密签名,在服务器端验证签名内容,防止被篡改;

  3.最后是对一般的接口访问,都需要使用用户身份的token进行校验,只要检查通过才允许访问数据。

 

  Web API接口的访问方式,大概可以分为几类:

  1)使用用户名密码。这种方式比较简单,可以有效识别用户的身份(如包括用户信息、密码、或者相关的接口权限等等)。验证成功后,返回相关的数据。

  2)使用安全签名。这种方式提交的数据,URL连接的签名参数是经过安全一定规则的加密的,服务器收到数据后也经过同样规则的安全加密,确认数据没有被中途篡改后,再进行数据修改处理。因此我们可以为不同客户端,如Web/APP/Winfrom等不同接入方式指定不同的加密秘钥,但是秘钥是双方约定的,并不在网络连接上传输,连接传输的一般是这个接入的AppID,服务器通过这个AppID来进行签名参数的加密对比。目前微信后台的回调处理机制,应该就是这么处理的。

  3)公开的接口调用,不需要传入用户令牌、或者对参数进行加密签名的,这种接口一般较少,只是提供一些很常规的数据显示而已。

   

 

  web api 安全校验

  使用用户名密码的实现方式比较简单,这里就不说明如何实现了。就讲一讲安全签名的实现。由于Web API的调用,都是一种无状态的调用方式,所有的接口请求,都要带安全签名。

  

 

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

 public class QueryData
    {
        public QueryData()
        {

        }

        public QueryData(IEnumerable<KeyValuePair<string, string>> paramList)
        {
            // TODO: Complete member initialization
            try
            {
                if (paramList == null)
                {
                    throw new Exception("请求参数为空!");
                }

                foreach (var param in paramList)
                {
                    m_values[param.Key] = param.Value; //
                }
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }

        //采用排序的Dictionary的好处是方便对数据包进行签名,不用再签名之前再做一次排序
        private SortedDictionary<string, object> m_values = new SortedDictionary<string, object>();

        /**
        * 设置某个字段的值
        * @param key 字段名
         * @param value 字段值
        */
        public void SetValue(string key, object value)
        {
            m_values[key] = value;
        }

        /**
        * 根据字段名获取某个字段的值
        * @param key 字段名
         * @return key对应的字段值
        */
        public object GetValue(string key)
        {
            object o = null;
            m_values.TryGetValue(key, out o);
            return o;
        }

        /**
         * 判断某个字段是否已设置
         * @param key 字段名
         * @return 若字段key已被设置,则返回true,否则返回false
         */
        public bool IsSet(string key)
        {
            object o = null;
            m_values.TryGetValue(key, out o);
            if (null != o)
                return true;
            else
                return false;
        }

        public string ToUrl()
        {
            string buff = "";
            foreach (KeyValuePair<string, object> pair in m_values)
            {
                if (pair.Value == null)
                {
                    throw new Exception("内部含有值为null的字段!");
                }

                if (pair.Key != "sign" && pair.Value.ToString() != "")
                {
                    buff += pair.Key + "=" + pair.Value + "&";
                }
            }
            buff = buff.Trim('&');
            return buff;
        }

        public string MakeSign(string appKey = "test")
        {
            //转url格式
            string str = ToUrl();
            //在string后加入API KEY
            str += "&key=" + appKey;
            //MD5加密
            var md5 = MD5.Create();
            var bs = md5.ComputeHash(Encoding.UTF8.GetBytes(str));
            var sb = new StringBuilder();
            foreach (byte b in bs)
            {
                sb.Append(b.ToString("x2"));
            }
            //所有字符转为大写
            return sb.ToString().ToUpper();
        }

        public bool CheckSign()
        {
            //如果没有设置签名,则跳过检测
            if (!IsSet("sign"))
            {
                throw new Exception("签名存在但不合法!");
            }
            //如果设置了签名但是签名为空,则抛异常
            else if (GetValue("sign") == null || GetValue("sign").ToString() == "")
            {
                throw new Exception("签名存在但不合法!");
            }

            //获取接收到的签名
            string return_sign = GetValue("sign").ToString();

            //在本地计算新的签名
            string cal_sign = MakeSign();

            if (cal_sign == return_sign)
            {
                return true;
            }
            return false;
        }
    }

  代码供大家参考和学习,正式的项目可以根据自己公司的需要去设计,后续也会开源相关的完整项目源代码。

 

时间: 2024-11-05 17:58:41

Web API系列(二)接口安全和参数校验的相关文章

Web API系列(三)统一异常处理

前面讲了webapi的安全验证和参数安全,不清楚的朋友,可以看看前面的文章,<Web API系列(二)接口安全和参数校验>,本文主要介绍Web API异常结果的处理.作为内部或者是对外提供的统一webapi 接口,统一的异常处理,把正确的信息返回给调用者很重要.这样可以让接口开发人员,了解具体的原因所在,这样可以得到有效的错误处理. 需要注意的是,webapi异常的状态码,尽量不要和业务状态码混淆.可以分为两个不同的字段,或者是状态码的规则不同.相关返回数据的格式,可以参考,前面的文章. 1.

【转】ASP.NET WEB API系列教程

from: 西瓜小强 http://www.cnblogs.com/risk/category/406988.html    ASP.NET Web API教程(六) 安全与身份认证 摘要: 在实际的项目应用中,很多时候都需要保证数据的安全和可靠,如何来保证数据的安全呢?做法有很多,最常见的就是进行身份验证.验证通过,根据验证过的身份给与对应访问权限.同在Web Api中如何实现身份认证呢?接下来的内容就详细的分享 Web API身份认证.首先扩展自定义身份验证添加类 CustomA...阅读全

Web API系列(一)设计经验与总结

在移动互联网的时代, Web服务已经成为了异构系统之间的互联与集成的主要手段,各种 Web服务几乎都采用REST风格的Web Api来构建. 通过Http协议的形式来. 以Get/Post方式发送请求, 返回json格式(数据更小巧且自描述能力强)的数据.这里就不在介绍REST API 的好处和不足.这些网上一大堆资料.今天就说说,如何构建优秀的REST API ? 目前,各大互联网公司, 对自身的REST Api设计有各自的标准,他们的Api 的设计也非常成熟. 那么,我们应该如何更好的设计我

构建安全的Xml Web Service系列(二)

web|xml|安全 上一篇文章地址:构建安全的Xml Web Service系列一之初探使用Soap头 要分析Xml Web Service的安全性,首先要解决的问题是我们能了解和清楚Soap消息的格式和内容,如果获得不了SoapMessage,分析如何能构建安全Xml web service也就无从下手,即使分析出来,自己也可能模模糊糊,不能定论.下面就分析下如何获得SoapMessage. 首先介绍一个类-SoapExtension,msdn对这个类的备注为:ASP.NET 允许通过扩展性

ASP.NET Web API(二) 安全验证之使用HTTP基本认证

在前一篇文章ASP.NET Web API(一):使用初探,GET和POST数据中,我们初步接触了微软的REST API: Web API. 我们在接触了Web API的后就立马发现了有安全验证的需求,所以这篇文章我们先来讨论下 安全验证一个最简单的方法:使用HTTP基本认证. HTTP基本认证原理 在HTTP协议进行通信的过 程中,HTTP协议定义了基本认证过程以允许HTTP服务器对WEB浏览器进行用户身份认证的方法,当一个客户端 向HTTP服务器进行数据请求时,如果客户端未被认证,则HTTP

Hello Web API系列教程:Web API与国际化

软件国际化是在软件设计和文档开发过程中,使得功能和代码设计能处理多种语言和文化习俗,在创建不同语言版本时,不需要重新设计源程序代码的软件工程方法.这在很多成熟的软件开发平台中非常常见.对于.net开发者来说,我们一般可以通过以下两种方式来实现软件的国际化. 语言配置文件 资源文件 在.net平台中,软件的国际化主要依靠工作线程的国际化来完成.在.net框架的的处理线程中,我们通过设置Thread.CurrentCulture属性来实现对日期.时间.数字.货币值.文本的排序顺序,负载约定和字符串比

Asp.Net Web API 2 官网菜鸟学习系列导航[持续更新中]

原文:Asp.Net Web API 2 官网菜鸟学习系列导航[持续更新中] 前言 本来一直参见于微软官网进行学习的, 官网网址http://www.asp.net/web-api.出于自己想锻炼一下学习阅读英文文章的目的,又可以学习下微软新发布的技术,其实也很久了,但自己菜鸟一枚,对自己来说都是新技术了.鉴于以上两个原因,本人打算借助google翻译和有道词典,来翻译学习这个系列,并通过博客园来记录自己的翻译学习过程.由于自己阅读水平的确太菜,在借助工具的情况下,有时候搞出来的也是蹩脚的语句,

Winform混合式开发框架访问Web API接口的处理

在我的混合式开发框架里面,集成了WebAPI的访问,这种访问方式不仅可以实现简便的数据交换,而且可以在多种平台上进行接入,如Winform程序.Web网站.移动端APP等多种接入方式,Web API的处理方式和微信提供的接口处理规则类似,也是通过向服务器获得访问令牌(AccessToken),然后传递给每个Web API接口,实现数据的交换处理.本篇随笔主要介绍混合框架中Winform对Web API访问的处理. 1.Web API接入方式介绍 <混合式开发框架>混合了Web API接口访问.

Web APi 2.0优点和特点?在Web APi中如何启动Session状态?

前言 曾几何时,微软基于Web服务技术给出最流行的基于XML且以扩展名为.asmx结尾的Web Service,此服务在.NET Framework中风靡一时同时也被.NET业界同仁所青睐,几年后在此基础上又扩展成为了WCF,基于SOAP协议,基于WCF标准需要一些配置上的改变.现如今,大势所趋我们只需要HTTP协议以及更加优美的JSON格式,这时将不得不出现一个更加轻量级的Web服务技术.当然,Web Service和WCF虽然有其局限性但是其仍被许多企业所广泛应用,说明一时半会还不会被淘汰,