如何写出安全的API接口?接口参数加密签名设计思路
开发中经常用到接口,尤其是在面向服务的soa架构中,数据交互全是用的接口。
几年以前我认为,我写个接口,不向任何人告知我的接口地址,我的接口就是安全的,现在回想真是too young,too simple。但凡部署在广域网的应用程序,随随便便的好多工具可以根据ip或域名扫描应用程序的所有暴露的接口,进而分析参数,注入程序,分分钟被攻击。
那咋才能保证接口的安全性呢?
(一)面临的主要安全问题
a.网络环境假设:
a1.假设公共网络(Internet,如:WIFI、非家庭网络、非办公网络等) 是不安全的,一切基于HTTP协议的请求/响应(Request or Response)都是可以被截获的、篡改、重放(重发)的。
b.接口安全要求:
b1.防伪装攻击(案例:在公共网络环境中,第三方 有意或恶意 的调用我们的接口)
b2.防篡改攻击(案例:在公共网络环境中,请求头/查询字符串/内容 在传输过程被修改)
b3.防重放攻击(案例:在公共网络环境中,请求被截获,稍后被重放或多次重放)
b4.防数据信息泄漏(案例:截获用户登录请求,截获到账号、密码等)
(二)可参考的商业标准
可参见: HTTP数据传输安全方案 HTTPS(HTTP安全商业标准)
http://baike.baidu.com/view/14121.htm
(三)可参考国内互联网厂商参考
新浪OpenAPI、腾讯、淘宝 等。
(四)设计原则
1.轻量级
2.适合于异构系统(跨操作系统、多语言简易实现)
3.易于开发
4.易于测试
5.易于部署
6.满足接口安全需求(满足b1 b2 b3要求),无过度设计。
其它:接口安全要求b4部分,主要针对目前用户中心的登录接口
设计原则是:使用HTTPS安全协议 或 传输内容使用非对称加密,目前我们采用的后者。
(五)适用范围
1.所有写操作接口(增、删、改 操作)
2.非公开的读接口(如:涉密/敏感/隐私 等信息)
(六)接口参数签名 实现思路参考
必要的输入参数
|
参数名 |
类型 |
必选 |
描述 |
| _appid | string | 是 | 调用方身份ID,接口提供方用此来识别调不同的调用者,该参数是API基本规范的一部分,请详见API公共规范。 |
|
_sign |
string |
是 |
一次接口调用的签名值,服务器端 “防止 伪装请求/防篡改/ 防重发” 识别的重要依据。 |
|
_timestamp |
Int |
是 |
时间戳(long Timestamp = DateTime.Now.Ticks;) |
签名算法过程:
1.对除签名外的所有请求参数按key做的升序排列,value无需编码。
(假设当前时间的时间戳是12345678)
例如:有c=3,b=2,a=1 三个参,另加上时间戳后, 按key排序后为:a=1,b=2,c=3,_timestamp=12345678。
2 把参数名和参数值连接成字符串,得到拼装字符:a1b2c3_timestamp12345678
3 用申请到的appkey 连接到接拼装字符串头部和尾部,然后进行32位MD5加密,最后将到得MD5加密摘要转化成大写。
示例:假设appkey=test,md5(testa1b2c3_timestamp12345678test),取得MD5摘要值 C5F3EB5D7DC2748AED89E90AF00081E6 。
再看一个更具体的Sample Code:
如何得取如下请求的签名值:
http://api.demo.com/dog/add?1=壹&A=aaa&Z=zzz&_appid=club&_timestamp=12345678&a=AAA&z=ZZZ
C#实现代码如下 ( 请新建一个C#代码文件 SampleCode.cs ):
test()方法展示了如何取得该请的签名参数值 ( _sign=8B0E081689789CF66490E65BB8E1B0E7 ),现实业务中依据自己的情况,把创建请求的过程封装成公共方法,使得请求url的创建过程对开发人员透明,简化处理。
[下方会提供 .Net的 Sample Code]
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
.Net
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace test3
{
public class SampleCode
{
public static string test()
{
int _timestamp = ;
var param = new SortedDictionary<string, string>(new AsciiComparer());
param.Add("z", "ZZZ");
param.Add("a", "AAA");
param.Add("Z", "zzz");
param.Add("A", "aaa");
param.Add("", "贰");
param.Add("", "壹");
param.Add("_appid", "club");
param.Add("_timestamp", _timestamp.ToString());
string _sign = GetSign(param);
string urlParam = string.Join("&", param.Select(i => i.Key + "=" + i.Value));
string url = "http://api.demo.com/dog/add?" + urlParam + "&_sign=" + _sign;
return url;
}
public static string GetSign(SortedDictionary<string, string> paramList, string appKey = "test")
{
paramList.Remove("_sign");
StringBuilder sb = new StringBuilder(appKey);
foreach (var p in paramList)
sb.Append(p.Key).Append(p.Value);
sb.Append(appKey);
return GetMD5(sb.ToString());
}
public static string GetMD5(string str)
{
if (string.IsNullOrEmpty(str))
return str;
var sb = new StringBuilder();
var md5 = System.Security.Cryptography.MD5.Create();
var output = md5.ComputeHash(Encoding.UTF8.GetBytes(str));
for (int i = ; i < output.Length; i++)
sb.Append(output[i].ToString("X").PadLeft(, ''));
return sb.ToString();
}
}
/// <summary>
/// 基于ASCII码排序规则的String比较器
/// Author:HeDaHong
/// </summary>
public class AsciiComparer : System.Collections.Generic.IComparer<string>
{
public int Compare(string a, string b)
{
if (a == b)
return ;
else if (string.IsNullOrEmpty(a))
return -;
else if (string.IsNullOrEmpty(b))
return ;
if (a.Length <= b.Length)
{
for (int i = ; i < a.Length; i++)
{
if (a[i] < b[i])
return -;
else if (a[i] > b[i])
return ;
else
continue;
}
return a.Length == b.Length ? : -;
}
else
{
for (int i = ; i < b.Length; i++)
{
if (a[i] < b[i])
return -;
else if (a[i] > b[i])
return ;
else
continue;
}
return ;
}
}
}
}
总结:
- 接口调用方和接口提供方约定好统一的参数加密算法
- 接口调用方在调用时把加密后的_sign放在参数中去请求接口
- 接口提供方接到响应后,判断时间戳是不是在有效时间内(这个时间间隔根据你的安全范围可以是10分钟,5分钟,20秒等,过期失效,前提是需要保证接口提供方和调用方的服务器时间为准确的网络同步时间)
- 把参数中除了_sign以外的参数进行加密,然后把加密结果和传过来的_sign比较,相同则执行调用请求。
有同学说难以理解,我这两天写个demo,请参考下一篇文章:http://www.cnblogs.com/codeon/p/6123863.html
如何写出安全的API接口?接口参数加密签名设计思路的更多相关文章
- 如何写出安全的 API 接口?接口参数加密签名设计思路
原文链接:http://blog.csdn.net/ma_jiang/article/details/53636840
- 如何写出安全的API接口(参数加密+超时处理+私钥验证+Https)- 续(附demo)
上篇文章说到接口安全的设计思路,如果没有看到上篇博客,建议看完再来看这个. 通过园友们的讨论,以及我自己查了些资料,然后对接口安全做一个相对完善的总结,承诺给大家写个demo,今天一并放出. 对于安全 ...
- 如何写出安全的API接口
通过园友们的讨论,以及我自己查了些资料,然后对接口安全做一个相对完善的总结,承诺给大家写个demo,今天一并放出. 对于安全也是相对的,下面我来根据安全级别分析 1.完全开放的接口 有没有这样的接口, ...
- API接口通讯参数规范(2)
针对[API接口通讯参数规范]这篇文章留下的几个问题进行探讨. 问题1 试想一下,如果一个http请求返回一个500给我们,那我们是不是都不用看详情都知道该次请求发生了什么?这正是一个标准的结果码意义 ...
- Java | Spring Boot Swagger2 集成REST ful API 生成接口文档
Spring Boot Swagger2 集成REST ful API 生成接口文档 原文 简介 由于Spring Boot 的特性,用来开发 REST ful 变得非常容易,并且结合 Swagg ...
- API接口防止参数篡改和重放攻击
{近期领导要求我对公司业务的支付类的ocr接口做研究,是否存在支付接口重放攻击,so.....} API重放攻击(Replay Attacks)又称重播攻击.回放攻击.他的原理就是把之前窃听到的数据原 ...
- 为spring boot 写的Controller中的rest接口配置swagger
1.pom.xml文件中加入下列依赖: <dependency> <groupId>io.springfox</groupId> <artifactId> ...
- API服务接口签名代码与设计,如果你的接口不走SSL的话?
在看下面文章之前,我们先问几个问题 rest 服务为什么需要签名? 签名的几种方式? 我认为的比较方便的快捷的签名方式(如果有大神持不同意见,可以交流!)? 怎么实现验签过程 ? 开放式open ap ...
- 【开源】.Net Api开放接口文档网站
开源地址:http://git.oschina.net/chejiangyi/ApiView 开源QQ群: .net 开源基础服务 238543768 ApiView .net api的接口文档查看 ...
随机推荐
- React Native环境配置之Windows版本搭建
接近年底了,回想这一年都做了啥,学习了啥,然后突然发现,这一年买了不少书,看是看了,就没有完整看完的.悲催. 然后,最近项目也不是很紧了,所以抽空学习了H5.自学啃书还是很无趣的,虽然Head Fir ...
- Atitit.研发团队与公司绩效管理的原理概论的attilax总结
Atitit.研发团队与公司绩效管理的原理概论的attilax总结 1. 四个理念 1 1.1. 绩效管理的三个目的.四个环节.五个关键2 1.2. 绩效目标smart2 2. 考核对象2 3. 绩效 ...
- HTML5 程序设计 - 使用HTML5 Canvas API
请你跟着本篇示例代码实现每个示例,30分钟后,你会高喊:“HTML5 Canvas?!在哥面前,那都不是事儿!” 呵呵.不要被滚动条吓到,很多都是代码和图片.我没有分开写,不过上面给大家提供了目录,方 ...
- [AlwaysOn Availability Groups]健康模型 Part 1——概述
健康模型概述 在成功部署AG之后,跟踪和维护健康状况是很重要的. 1.AG健康模型概述 AG的健康模型是基于策略管理(Policy Based Management PBM)的.如果不熟悉这个特性,可 ...
- BZOJ1012: [JSOI2008]最大数maxnumber [线段树 | 单调栈+二分]
1012: [JSOI2008]最大数maxnumber Time Limit: 3 Sec Memory Limit: 162 MBSubmit: 8748 Solved: 3835[Submi ...
- Linux下的C Socket编程 -- server端的继续研究
Linux下的C Socket编程(四) 延长server的生命周期 在前面的一个个例子中,server在处理完一个连接后便会立即结束掉自己,然而这种server并不科学啊,server应该是能够一直 ...
- 您真的理解了SQLSERVER的日志链了吗?
您真的理解了SQLSERVER的日志链了吗? 先感谢宋沄剑给本人指点迷津,还有郭忠辉童鞋今天在QQ群里抛出的问题 这个问题跟宋沄剑讨论了三天,再次感谢宋沄剑 一直以来,SQLSERVER提供了一个非常 ...
- Mono 4.0 Mac上运行asp.net mvc 5.2.3
Mono 4.0 已经发布,二进制包已经准备好,具体的发布说明参见:http://www.mono-project.com/docs/about-mono/releases/4.0.0/. 今天在Ma ...
- 【Knockout.js 学习体验之旅】(3)模板绑定
本文是[Knockout.js 学习体验之旅]系列文章的第3篇,所有demo均基于目前knockout.js的最新版本(3.4.0).小茄才识有限,文中若有不当之处,还望大家指出. 目录: [Knoc ...
- docker创建私有仓库
由于网速和大中华局域网效果,使得我们在DockerHub下载镜像的速度很慢,甚至一些国内的镜像仓库,也感觉速度不是很好.所以,很有必要在本地或者一个我们访问很快速的地方(自己的云服务器)搭建一套镜像仓 ...