API接口设计:防参数篡改+防二次请求(防重放)

API接口设计:防参数篡改+防二次请求(防重放)

API接口由于需要供第三方服务调用,所以必须暴露到外网,并提供了具体请求地址和请求参数

为了防止被第别有用心之人获取到真实请求参数后再次发起请求获取信息,需要采取很多安全机制

1.首先: 需要采用https方式对第三方提供接口,数据的加密传输会更安全,即便是被破解,也需要耗费更多时间

2.其次:需要有安全的后台验证机制【本文重点】,达到防参数篡改+防二次请求


主要防御措施可以归纳为两点:

对请求的合法性进行校验

对请求的数据进行校验


防止重放攻击必须要保证请求仅一次有效

需要通过在请求体中携带当前请求的唯一标识,并且进行签名防止被篡改。

所以防止重放攻击需要建立在防止签名被串改的基础之上。

请求参数防篡改

采用https协议可以将传输的明文进行加密,但是黑客仍然可以截获传输的数据包,进一步伪造请求进行重放攻击。如果黑客使用特殊手段让请求方设备使用了伪造的证书进行通信,那么https加密的内容也将会被解密。

在API接口中我们除了使用https协议进行通信外,还需要有自己的一套加解密机制,对请求参数进行保护,防止被篡改。

过程如下:

客户端使用约定好的秘钥对传输参数进行加密,得到签名值signature,并且将签名值也放入请求参数中,发送请求给服务端

服务端接收客户端的请求,然后使用约定好的秘钥对请求的参数(除了signature以外)再次进行签名,得到签名值autograph。

服务端对比signature和autograph的值,如果对比一致,认定为合法请求。如果对比不一致,说明参数被篡改,认定为非法请求。

因为黑客不知道签名的秘钥,所以即使截取到请求数据,对请求参数进行篡改,但是却无法对参数进行签名,无法得到修改后参数的签名值signature。

签名的秘钥我们可以使用很多方案,可以采用对称加密或者非对称加密。

( 古月: 关于怎么签名可以参考阿里的文档

请求签名说明文档_用户指南(调用 API)_API 网关-阿里云

https://help.aliyun.com/document_detail/29475.html?spm=a2c4g.11186623.2.3.nRdYli

接口鉴权 - 标签 - 文档平台 - 腾讯云

https://cloud.tencent.com/document/product/651/18355  )


防止重放攻击

基于timestamp的方案

每次HTTP请求,都需要加上timestamp参数,然后把timestamp和其他参数一起进行数字签名。因为一次正常的HTTP请求,从发出到达服务器一般都不会超过60s,所以服务器收到HTTP请求之后,首先判断时间戳参数与当前时间相比较,是否超过了60s,如果超过了则认为是非法的请求。

一般情况下,黑客从抓包重放请求耗时远远超过了60s,所以此时请求中的timestamp参数已经失效了。

如果黑客修改timestamp参数为当前的时间戳,则signature参数对应的数字签名就会失效,因为黑客不知道签名秘钥,没有办法生成新的数字签名。

但这种方式的漏洞也是显而易见的,如果在60s之后进行重放攻击,那就没办法了,所以这种方式不能保证请求仅一次有效。

基于nonce的方案

nonce的意思是仅一次有效的随机字符串,要求每次请求时,该参数要保证不同,所以该参数一般与时间戳有关,我们这里为了方便起见,直接使用时间戳的16进制,实际使用时可以加上客户端的ip地址,mac地址等信息做个哈希之后,作为nonce参数。

我们将每次请求的nonce参数存储到一个“集合”中,可以json格式存储到数据库或缓存中。

每次处理HTTP请求时,首先判断该请求的nonce参数是否在该“集合”中,如果存在则认为是非法请求。

nonce参数在首次请求时,已经被存储到了服务器上的“集合”中,再次发送请求会被识别并拒绝。

nonce参数作为数字签名的一部分,是无法篡改的,因为黑客不清楚token,所以不能生成新的sign。

这种方式也有很大的问题,那就是存储nonce参数的“集合”会越来越大,验证nonce是否存在“集合”中的耗时会越来越长。我们不能让nonce“集合”无限大,所以需要定期清理该“集合”,但是一旦该“集合”被清理,我们就无法验证被清理了的nonce参数了。也就是说,假设该“集合”平均1天清理一次的话,我们抓取到的该url,虽然当时无法进行重放攻击,但是我们还是可以每隔一天进行一次重放攻击的。而且存储24小时内,所有请求的“nonce”参数,也是一笔不小的开销。

基于timestamp和nonce的方案

nonce的一次性可以解决timestamp参数60s的问题,timestamp可以解决nonce参数“集合”越来越大的问题。

防止重放攻击一般和防止请求参数被串改一起做,请求的Headers数据如下图所示。


我们在timestamp方案的基础上,加上nonce参数,因为timstamp参数对于超过60s的请求,都认为非法请求,所以我们只需要存储60s的nonce参数的“集合”即可。


最终实现代码(网关层验证):

复制代码

1 public class APIAuth extends ZuulFilter {

2    @Override

3    public String filterType() {

4        return "pre";

5    }

6

7    @Override

8    public int filterOrder() {

9        return 0;

10    }

11

12    @Override

13    public boolean shouldFilter() {

14        return true;

15    }

16

17    @Override

18    public Object run() {

19        RequestContext ctx = RequestContext.getCurrentContext();

20        HttpServletRequest request = ctx.getRequest();

21

22        String token = request.getHeader("token");

23        String timestamp = request.getHeader("timestamp");

24        String nonce = request.getHeader("nonce");

25        String sign = request.getHeader("sign");

26

27        //时间限制配置

28        int timeLimit = 60;

29

30        ctx.setSendZuulResponse(false);

31

32        //请求头参数非空验证

33        if (StringUtils.isEmpty(token) || StringUtils.isEmpty(timestamp) || StringUtils.isEmpty(nonce) || StringUtils.isEmpty(sign)) {

34            ctx.setResponseBody(JSON.toJSONString(new Result("-1", "请求头参数不正确")));

35            return null;

36        }

37

38        //请求时间和现在时间对比验证,发起请求时间和服务器时间不能超过timeLimit秒

39        if (StringUtils.timeDiffSeconds(new Date(), timestamp) > timeLimit) {

40            ctx.setResponseBody(JSON.toJSONString(new Result("-1", "请求发起时间超过服务器限制")));

41            return null;

42        }

43

44        //验证用户信息

45        UserInfo userInfo = UserInfoUtil.getInfoByToken(token);

46        if (userInfo == null) {

47            ctx.setResponseBody(JSON.toJSONString(new Result("-1", "错误的token信息")));

48            return null;

49        }

50

51        //验证相同noce的请求是否已经存在,存在表示为重复请求

52        if (NoceUtil.exsit(userInfo, nonce)) {

53            ctx.setResponseBody(JSON.toJSONString(new Result("-1", "重复的请求")));

54            return null;

55        } else {

56            //如果noce没有在缓存中,则需要加入,并设置过期时间为timeLimit秒

57            NoceUtil.addNoce(userInfo, nonce, timeLimit);

58        }

59

60        //服务器生成签名与header中签名对比

61        String serverSign = SignUtil.getSign(userinfo, token, timestamp, nonce, request);

62        if (!serverSign.equals(sign)) {

63            ctx.setResponseBody(JSON.toJSONString(new Result("-1", "错误的签名信息")));

64            return null;

65        }

66

67        ctx.setSendZuulResponse(true);

68        return null;

69    }

70 }

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,117评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,328评论 1 293
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,839评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,007评论 0 206
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,384评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,629评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,880评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,593评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,313评论 1 243
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,575评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,066评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,392评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,052评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,082评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,844评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,662评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,575评论 2 270

推荐阅读更多精彩内容

  • 一、API重放攻击 我们在设计接口的时候,最怕一个接口被用户截取用于重放攻击。重放攻击是什么呢?就是把你的请求原封...
    爱情小傻蛋阅读 17,758评论 4 10
  • 说说API的防重放机制 我们在设计接口的时候,最怕一个接口被用户截取用于重放攻击。重放攻击是什么呢?就是把你的请求...
    MxlZlh阅读 2,247评论 2 18
  • 我们在设计接口的时候,最怕一个接口被用户截取用于重放攻击。重放攻击是什么呢?就是把你的请求原封不动地再发送一次,两...
    devLionel阅读 1,378评论 0 2
  • 接口安全问题 请求身份是否合法? 请求参数是否被篡改? 请求是否唯一? AccessKey&SecretKey (...
    Joker_Coding阅读 61,397评论 11 74
  • 背景 最近,公司由于业务繁忙人手不够,将部分业务外包给第三方公司做。在开发的过程中,遇到了外部调用内部敏感接口场景...
    youthcity阅读 3,876评论 0 51