以前简单介绍过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核心安全校验代码片断:

  1. public class QueryData
  2. {
  3. public QueryData()
  4. {
  5.  
  6. }
  7.  
  8. public QueryData(IEnumerable<KeyValuePair<string, string>> paramList)
  9. {
  10. // TODO: Complete member initialization
  11. try
  12. {
  13. if (paramList == null)
  14. {
  15. throw new Exception("请求参数为空!");
  16. }
  17.  
  18. foreach (var param in paramList)
  19. {
  20. m_values[param.Key] = param.Value; //
  21. }
  22. }
  23. catch (Exception ex)
  24. {
  25. throw new Exception(ex.Message);
  26. }
  27. }
  28.  
  29. //采用排序的Dictionary的好处是方便对数据包进行签名,不用再签名之前再做一次排序
  30. private SortedDictionary<string, object> m_values = new SortedDictionary<string, object>();
  31.  
  32. /**
  33. * 设置某个字段的值
  34. * @param key 字段名
  35. * @param value 字段值
  36. */
  37. public void SetValue(string key, object value)
  38. {
  39. m_values[key] = value;
  40. }
  41.  
  42. /**
  43. * 根据字段名获取某个字段的值
  44. * @param key 字段名
  45. * @return key对应的字段值
  46. */
  47. public object GetValue(string key)
  48. {
  49. object o = null;
  50. m_values.TryGetValue(key, out o);
  51. return o;
  52. }
  53.  
  54. /**
  55. * 判断某个字段是否已设置
  56. * @param key 字段名
  57. * @return 若字段key已被设置,则返回true,否则返回false
  58. */
  59. public bool IsSet(string key)
  60. {
  61. object o = null;
  62. m_values.TryGetValue(key, out o);
  63. if (null != o)
  64. return true;
  65. else
  66. return false;
  67. }
  68.  
  69. public string ToUrl()
  70. {
  71. string buff = "";
  72. foreach (KeyValuePair<string, object> pair in m_values)
  73. {
  74. if (pair.Value == null)
  75. {
  76. throw new Exception("内部含有值为null的字段!");
  77. }
  78.  
  79. if (pair.Key != "sign" && pair.Value.ToString() != "")
  80. {
  81. buff += pair.Key + "=" + pair.Value + "&";
  82. }
  83. }
  84. buff = buff.Trim('&');
  85. return buff;
  86. }
  87.  
  88. public string MakeSign(string appKey = "test")
  89. {
  90. //转url格式
  91. string str = ToUrl();
  92. //在string后加入API KEY
  93. str += "&key=" + appKey;
  94. //MD5加密
  95. var md5 = MD5.Create();
  96. var bs = md5.ComputeHash(Encoding.UTF8.GetBytes(str));
  97. var sb = new StringBuilder();
  98. foreach (byte b in bs)
  99. {
  100. sb.Append(b.ToString("x2"));
  101. }
  102. //所有字符转为大写
  103. return sb.ToString().ToUpper();
  104. }
  105.  
  106. public bool CheckSign()
  107. {
  108. //如果没有设置签名,则跳过检测
  109. if (!IsSet("sign"))
  110. {
  111. throw new Exception("签名存在但不合法!");
  112. }
  113. //如果设置了签名但是签名为空,则抛异常
  114. else if (GetValue("sign") == null || GetValue("sign").ToString() == "")
  115. {
  116. throw new Exception("签名存在但不合法!");
  117. }
  118.  
  119. //获取接收到的签名
  120. string return_sign = GetValue("sign").ToString();
  121.  
  122. //在本地计算新的签名
  123. string cal_sign = MakeSign();
  124.  
  125. if (cal_sign == return_sign)
  126. {
  127. return true;
  128. }
  129. return false;
  130. }
  131. }

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

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

  1. Redis总结(五)缓存雪崩和缓存穿透等问题 Web API系列(三)统一异常处理 C#总结(一)AutoResetEvent的使用介绍(用AutoResetEvent实现同步) C#总结(二)事件Event 介绍总结 C#总结(三)DataGridView增加全选列 Web API系列(二)接口安全和参数校验 RabbitMQ学习系列(六): RabbitMQ 高可用集群

    Redis总结(五)缓存雪崩和缓存穿透等问题   前面讲过一些redis 缓存的使用和数据持久化.感兴趣的朋友可以看看之前的文章,http://www.cnblogs.com/zhangweizhon ...

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

    前面讲了webapi的安全验证和参数安全,不清楚的朋友,可以看看前面的文章,<Web API系列(二)接口安全和参数校验>,本文主要介绍Web API异常结果的处理.作为内部或者是对外提供 ...

  3. Web Api 与 Andriod 接口对接开发经验

    最近一直急着在负责弄Asp.Net Web Api 与 Andriod 接口开发的对接工作! 刚听说要用Asp.Net Web Api去跟 Andriod 那端做接口对接工作,自己也是第一次接触Web ...

  4. Asp.Net Web Api 与 Andriod 接口对接开发经验,给小伙伴分享一下!

    最近一直急着在负责弄Asp.Net Web Api 与 Andriod 接口开发的对接工作! 刚听说要用Asp.Net Web Api去跟 Andriod 那端做接口对接工作,自己也是第一次接触Web ...

  5. Asp.Net Web Api 与 Andriod 接口对接开发

    Asp.Net Web Api 与 Andriod 接口对接开发经验,给小伙伴分享一下!   最近一直急着在负责弄Asp.Net Web Api 与 Andriod 接口开发的对接工作! 刚听说要用A ...

  6. Asp.Net Web API(二)

    创建一个Web API项目 第一步,创建以下项目 当然,你也可以创建一个Web API项目,利用 Web API模板,Web API模板使用 ASP.Net MVC提供API的帮助页. 添加Model ...

  7. Web API系列之三 基本功能实现

    Web API系列之二讲解了如何搭建一个WebApi的基架,本文主要在其基础之上实现基本的功能.下面开始逐步操作: 一.配置WebApi的路由-用于配置外部如何访问内部资源的url的规则 1.添加Gl ...

  8. ASP.NET Web API系列教程目录

    ASP.NET Web API系列教程目录 Introduction:What's This New Web API?引子:新的Web API是什么? Chapter 1: Getting Start ...

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

    from: 西瓜小强 http://www.cnblogs.com/risk/category/406988.html ASP.NET Web API教程(六) 安全与身份认证 摘要: 在实际的项目应 ...

随机推荐

  1. bitnami redmine版本由2.3.1升级至3.2.2过程

    环境: 操作系统为ubuntu13.**版本,非长期支持版. 安装目录:/opt/redmine-2.3.1-0/ 所有者用户:root 安装过程: 1. 备份2.3.1数据库 sudo /opt/r ...

  2. yii2中如何使用modal弹窗之基本使用

    作者:白狼 出处:http://www.manks.top/yii2_modal_baseuse.html 本文版权归作者,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接, ...

  3. SQL*Plus环境下创建PLUSTRACE角色

    普通用户在SQL*Plus中开启AUTOTRACE报告时,遇到SP2-0618: Cannot find the Session Identifier. Check PLUSTRACE role is ...

  4. 在双系统(Windows与Ubuntu)下删除Ubuntu启动项

    问题概述:因为在自己学习Linux的时候,按照网上的教程错误的删除了Ubuntu的一个内核驱动,导致Ubuntu不能启动.我想到的办法是重新安装系统,重装系统的第一步便是将Ubuntu从电脑中卸载.该 ...

  5. MYSQL 基本SQL语句

    复制表结构 CREATE TABLE 新表 SELECT * FROM 旧表 where 1=2 复制表结构和数据CREATE TABLE 新表 SELECT * FROM 旧表 查询重复数据: se ...

  6. SVN“验证位置时发生错误”的解决办法

    验证位置时发生错误:“org.tigris.subversion.javahl.ClientException...... 验证位置时发生错误:“org.tigris.subversion.javah ...

  7. 基于corosync+pacemaker+drbd+LNMP做web服务器的高可用集群

    实验系统:CentOS 6.6_x86_64 实验前提: 1)提前准备好编译环境,防火墙和selinux都关闭: 2)本配置共有两个测试节点,分别coro1和coro2,对应的IP地址分别为192.1 ...

  8. mysql workbench如何把已有的数据库导出ER模型

    mysql workbench的特长是创建表结构的,然后在结构图中,圈圈点点,很容易就利用可视化方式把数据库建好,然后再导入到数据库服务器中,这种办法很效率.但是有时我们有一个需求,事先没有建表结构模 ...

  9. [LeetCode] Expression Add Operators 表达式增加操作符

    Given a string that contains only digits 0-9 and a target value, return all possibilities to add ope ...

  10. openwrt下部署adbyby去广告大师 免luci 带自启动,自动开启透明代理

    最近朋友送了个360老路由器 C301,于是乎就掉进了智能路由器的坑, 玩智能路由器第一件事一定是去广告, 要么怎么对得起智能路由器- -! 路由器去广告当然首推广告屏蔽大师 www.adbyby.c ...