如何保证API接⼝的安全性
怎样防伪装攻击
防伪装攻击:即防⽌接⼝被其他⼈调⽤,此阶段可以理解为⽐如已经登录了,然后在请求其他接⼝的时候,通过Token授权机制来判断当前请求是否有效
Token是客户端访问服务端的凭证。
Token授权机制
⽤户⽤密码登录或者验证码登录成功后,服务器返回token(通常UUID)给客户端,并将Token-UserId以键值对的形式存放在缓存服务器中。
客户端将token保存在本地,发起后续的相关请求时,将token发回给服务器;
服务器检查token的有效性,有效则返回数据,若⽆效,分两种情况:
1. token错误,这时需要⽤户重新登录,获取正确的token
2. token过期,这时客户端需要再发起⼀次认证请求,获取新的token(具体的看服务端和客户端怎么约定处理)
安全隐患
Token被劫持:被劫持之后,可以伪造请求(重放攻击)和篡改参数(篡改攻击)
怎样防重放攻击
重放攻击:所谓重放攻击就是攻击者发送⼀个⽬的主机已接收过的包,来达到欺骗系统的⽬的,主要⽤于⾝份认证过程。⽐如⿊客通过抓包获取到了请求的HTTP报⽂,然后⿊客⾃⼰编写了⼀个类似的HTTP请求,发送给服务器
timestamp、nonce主要针对每个API保持唯⼀性
基于时间戳(timestamp)的⽅案
每次HTTP请求,都需要加上timestamp参数,然后把timestamp和其他参数⼀起进⾏数字签名。因为⼀次正常的HTTP请求,从发出到达服务器⼀般都不会超过60s,所以服务器收到HTTP请求之后,⾸先判断时间戳参数与当前时间相⽐较,是否超过了
60s,如果超过了则认为是⾮法的请求。
baidu/index/Info?uid=ZX07&stime=14232323&sign=128728364892304dhfj92932 如果⿊客修改stime参数为当前的时间戳,则sign参数对应的数字签名就会失效,因为⿊客不知道token值,没有办法⽣成新的数字签名
存在的问题:⿊通过抓包发送请到服务端求⼀般都会超过60S了,但是如果是在60s之内进⾏重放攻击,那就没办法了,所以这种⽅式不能保证接⼝被多次调⽤。
基于nonce的⽅案
nonce(Number once)的意思是仅⼀次有效的随机字符串,要求每次请求时,该参数要保证不同,所以该参数⼀般与时间戳有关,服务端会把每⼀次请求的nonce保存到数据
⼯作流程:每次处理HTTP请求时,⾸先判断该请求的nonce参数是否在服务端数据库中,如果存在则认为是⾮法请求
api接口和sdk接口的区别让我们看⼀个实际的列⼦:
baidu/index/Info?uid=ZX07&nonce=53sdkjskd&sign=128728364892304dhfj92932 nonce参数在⾸次请求时,已经被存储到了服务器上的“集合”中,再次发送请求会被识别并拒绝。 nonce参数作为数字签名的⼀部分,是⽆法篡改的,因为⿊客不清楚token,所以不能⽣成新的sign。
存在的问题:那就是对服务器来说永久存储所有接收到的nonce的代价是⾮常⼤的
[最佳⽅案]基于timestamp和nonce的⽅案
nonce的⼀次性可以解决timestamp参数时间限制的问题,timestamp可以解决nonce参数在数据库“集合”越来越⼤的问题。在timestamp⽅案的基础上,加上nonce参数,因为timstamp参数对于超过60s的请求,都认为⾮法请求,所以我们只需要存储60s的nonce参数的“集合”即可让我们看⼀个实际的列⼦:
baidu/index/Info?uid=ZX07&stime=34334232323&nonce=53sdkjskd&sign=128728364892304dhfj92932 # 如果在60s内,重放该HTTP请求,因为nonce参数已经在⾸次请求的时候被记录在服务器的nonce参数“集合”中,所以会被判断为⾮法请求。超过60s之
后,stime参数就会失效,此时因为⿊客不清楚token的值,所以⽆法重新⽣成签名
如何正确⽣成timestamp
问题:由于服务器的时间和客户端的时间是存在时间差的,所以客户端时间必须和服务端时间做校验
先请求服务器上的时间 ServerTime,然后记录下来,同时记录当前的时间 LocalTime1,当下次请求接⼝的时候,最新的时间即是:LocalTime2 - LocalTime1 + ServerTime
App启动后通过接⼝获取服务器时间 ServerTime,保存本地。并同时记录当前时间 LocalTime1
获取当前时间:LocalTime2(当前本地时间) - LocalTime1 + ServerTime
怎样防篡改攻击
签名机制
算法:signature(签名) = MD5算法(token+timestamp+nonce+业务参数)
将“API接⼝中的token、timestamp、nonce、业务参数"进⾏MD5算法加密,加密后的数据就是本次请求的签名signature,服务端接收到请求后以同样的算法得到签名,并跟当前的签名进⾏⽐对,如果不⼀样,说明参数被更改过,直接返回错误标识。
具体流程:
请求参数包括token、timestamp、nonce、业务参数、客户端signature(签名)
将token、timestamp、nonce、业务参数以字母升序(A-Z)排序,按'key1=value1'+ '&' + 'key2=value2'连接所有参数得到字符串signStr
将字符串signStr进⾏MD5运⾏得到新的签名newSignature
newSignature和客户端发送的signature做⽐较
OAuth2.0
如果接⼝属于开放的API,则适合使⽤OAuth2.0的认证机制来处理。
⽤来代替密码,供第三⽅应⽤使⽤,需要⽤户授权
应⽤通过凭证(Access Token)向资源服务器请求相关资源
HTTPS
HTTPS:HTTPS在HTTP的基础上添加了TSL/SSL安全协议,不过,HTTPS也不是绝对安全的,也存在被劫持的可能,但相对HTTP⽏庸置疑是更加安全的
缺点:服务器对HTTPS的配置相对有点复杂,还需要到CA申请证书,⽽且⼀般还是收费的。⽽且,HTTPS效率也⽐较低。⼀般,只有安全要求⽐较⾼的系统才会采⽤HTTPS,⽐如银⾏。⽽⼤部分对安全要求没那么⾼的App还是采⽤HTTP的⽅式
IP⽩名单
仅允许IP⽩名单内的IP访问,其余的IP均不允许访问,可⽤于鉴权,防⽌代理ip被乱⽤,个⼈⽬前还未曾过多涉及,所以不做更多阐述。总结
只有在token有效、timestamp未超时、缓存服务器中不存在nonce三种情况同时满⾜,接⼝请求才有效。服务端可以写⼀个过滤器对token、timestamp和nonce进⾏过滤和验证