接口加密的实现(原创)
目的:
1,防止恶意无限访问API;
2,对客户端进行安全验证;
3,所有接口都走https请求。
预期:
1,暴露的api接口只有有限的时间能够访问到,防止无线次数访问;
2,signature每次访问都会变化,一个客户端的一次请求只对应一个signature;
3,客户端和服务端同事存储应用密钥(AppSecret),传输过程中进行加密传输;
4,服务端约定加密算法,当客户端发送请求后,所有加密的值拼接到url上,服务端对该次请求进行验证,如果验证通过才去返回相应数据,传输更加安全;
5,能够对接多个用户,扩展性相对较好;
6,https加密传输,安全性高。
伪代码 :
客户端发送请求:
key
|
value
|
备注
|
---|---|---|
AppId | 应用id | |
AppSecret | 应用密钥 | |
timestamp | 请求发送时的时间戳 | |
noncestr | 随机数 | |
signature | 签名 | 需要结合以上内容进行计算 |
签名算法:
$string=AppId+noncestr+signature+timestamp;
Signature =md5(md5($string).$AppSecret);
未加密前的请求地址:http://www.a.com?AppId=1×tamp=2&noncestr=a
加密请求如下:https://www.a.com?AppId=1&noncestr=aaa×tamp=2&signature=789
服务端接收请求:
1,查询数据库,或者设置白名单,找到该Appid对应的AppSecret,即服务端定义合同密钥
$AppSecret='具体密钥';
1,获取url的所有参数,AppId=1&noncestr=aaa×tamp=2&signature=789
2,把字符串转换成数组
$Parameters=array(
'AppId'=>'1',
‘noncestr’=>'aaa',
'timestamp'=>'2',
'signature'=>'789'
);
3, 对当前传入参数进行加密运算
$server_signature=MD5(MD5($Parameters['AppId']+$Parameters['noncestr']+$Parameters['timestamp'])+$AppSecret);
4,和传入的$Parameters['signature']进行比较,如果相等则证明该次访问安全。
------------------------------------------------------华丽分割线------------------------------------------------------------------------------------
1,客户端发送的加密请求暴露怎么办,能一直访问吗?
if((服务器当前时间戳-当前url的毫秒值)>2分钟){
echo '当前url访问超时';
}
也就是说,暴露的url只能用2分钟,2分钟后这个url就不能请求道数据了,开发阶段可以将时间增大,这个时间可以自己定义,只要发送的请求在有效的时间得到相应就可以,生产环境的话,理论上可以5-10秒足够。
2,适用场景是什么?有什么缺点?
适用于客户端的数据传输,app的接口数据传输(如果不考虑认为反编译app的话);
缺点在于,如果使用的网站也是使用接口,那么存储加密算法必然会在前端(jquery)上做处理,加密算法及密钥都会暴露,加密无意义。
3,这样的好处?
通过加盐方式,隐藏用户的AppSecret,如果发现当前密钥有风险,可以直接上服务端重新生成(借鉴了微信公众平台),易于扩展;
服务端验证加密,通过才去返回数据;可以对多个客户端提供api接口服务。
4,能对ip进行限制吗?
$_config['whitelist']=array( '192.168.1.1','192.144.23.4');
if ( ! in_array('通过php获取当前ip地址',$_config['whitelist']))
{
echo '用户不在白名单内!不能请求到数据';
}