Loading [MathJax]/jax/output/CommonHTML/config.js
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >API接口设计:防参数篡改+防二次请求

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

作者头像
肖哥哥
发布于 2018-08-02 09:41:03
发布于 2018-08-02 09:41:03
13.9K30
代码可运行
举报
运行总次数:0
代码可运行

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

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

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

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

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

  • 对请求的合法性进行校验
  • 对请求的数据进行校验

防止重放攻击必须要保证请求仅一次有效 需要通过在请求体中携带当前请求的唯一标识,并且进行签名防止被篡改。 所以防止重放攻击需要建立在防止签名被串改的基础之上。

请求参数防篡改

采用https协议可以将传输的明文进行加密,但是黑客仍然可以截获传输的数据包,进一步伪造请求进行重放攻击。如果黑客使用特殊手段让请求方设备使用了伪造的证书进行通信,那么https加密的内容也将会被解密。 在API接口中我们除了使用https协议进行通信外,还需要有自己的一套加解密机制,对请求参数进行保护,防止被篡改。 过程如下:

  1. 客户端使用约定好的秘钥对传输参数进行加密,得到签名值signature,并且将签名值也放入请求参数中,发送请求给服务端
  2. 服务端接收客户端的请求,然后使用约定好的秘钥对请求的参数(除了signature以外)再次进行签名,得到签名值autograph。
  3. 服务端对比signature和autograph的值,如果对比一致,认定为合法请求。如果对比不一致,说明参数被篡改,认定为非法请求。

因为黑客不知道签名的秘钥,所以即使截取到请求数据,对请求参数进行篡改,但是却无法对参数进行签名,无法得到修改后参数的签名值signature。 签名的秘钥我们可以使用很多方案,可以采用对称加密或者非对称加密

防止重放攻击

基于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参数的“集合”即可。

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 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 }
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2018-07-25 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
3 条评论
热度
最新
这里还有个问题,就是客户端密钥得保存是个问题。这个应该也是会有泄露的风险
这里还有个问题,就是客户端密钥得保存是个问题。这个应该也是会有泄露的风险
回复回复1举报
timestamp 重放攻击 ,《如果在60s之后进行重放攻击》 这句话是错的,应该是在60s之内进行重放攻击,而不是60s之后
timestamp 重放攻击 ,《如果在60s之后进行重放攻击》 这句话是错的,应该是在60s之内进行重放攻击,而不是60s之后
111举报
确实,博主应该是笔误了
确实,博主应该是笔误了
回复回复点赞举报
推荐阅读
编辑精选文章
换一批
公司来了个大神,三方接口调用方案设计的真优雅~~
在为第三方系统提供接口的时候,肯定要考虑接口数据的安全问题,比如数据是否被篡改,数据是否已经过时,数据是否可以重复提交等问题。
程序员蜗牛
2024/04/22
2.9K0
公司来了个大神,三方接口调用方案设计的真优雅~~
电商系统中API接口防止参数篡改和重放攻击(小程序/APP)
来源:https://www.cnblogs.com/jurendage/p/12886352.html
良月柒
2021/01/25
1.4K0
电商系统中API接口防止参数篡改和重放攻击(小程序/APP)
企业API接口设计(token、timestamp、sign)之具体实现
Token:访问令牌access token, 用于接口中, 用于标识接口调用者的身份、凭证,减少用户名和密码的传输次数。一般情况下客户端(接口调用方)需要先向服务器端申请一个接口调用的账号,服务器会给出一个appId和一个key, key用于参数签名使用,注意key保存到客户端,需要做一些安全处理,防止泄露。
lyb-geek
2019/11/30
3.1K0
大厂案例 - 通用的三方接口调用方案设计(上)
在为第三方系统提供接口时,关键是确保数据的完整性、安全性和防止重复提交。以下是一个基于API密钥(Access Key/Secret Key)和回调机制的设计方案,具有多层次的安全保障。
小小工匠
2024/05/26
4.9K0
大厂案例 - 通用的三方接口调用方案设计(上)
如何保证API接口安全?
在实际的业务开发过程中,我们常常会碰到需要与第三方互联网公司进行技术对接,例如支付宝支付对接、微信支付对接、高德地图查询对接等等服务,如果你是一个创业型互联网,大部分可能都是对接别的公司api接口。
纯洁的微笑
2021/07/01
1.7K0
如何保证API接口安全?
三方接口调用设计方案
为保障三方接口的安全性,可采取多方面措施,包括使用 HTTPS 协议确保数据传输安全,利用 AK 和签名进行身份验证以及对请求验签来防止非法请求与重放攻击,还有对敏感数据进行加密传输等。不过具体实现细节会因项目需求而存在差异,并且在实际开发中,还需兼顾错误处理、异常情况处理以及日志记录等方面内容。
用户1142828
2024/12/08
2930
标准API接口设计规范
在设计和实现API接口时,我们经常需要处理一些敏感数据,例如用户的登录密码、银行卡号、身份证号码等。这些信息若以明文形式在网络上传输,将面临极大的安全风险,容易受到恶意监听和数据泄露的威胁。
Tinywan
2024/06/04
4780
标准API接口设计规范
SpringBoot 如何保证接口安全?老鸟们都是这么玩的!
对于互联网来说,只要你系统的接口暴露在外网,就避免不了接口安全问题。 如果你的接口在外网裸奔,只要让黑客知道接口的地址和参数就可以调用,那简直就是灾难。
闻说社
2023/03/13
1.6K0
这才叫 API 接口设计!
大家好,我是鱼皮,前段时间在 星球 里看到了一位小伙伴分享的文章《API 接口设计最佳实践》,我也读了一遍,写的确实好,给大家分享一下,相信对后端开发的小伙伴会很有帮助。
程序员鱼皮
2022/04/08
2.9K0
这才叫 API 接口设计!
如何保证API接口安全?
在实际的业务开发过程中,我们常常会碰到需要与第三方互联网公司进行技术对接,例如支付宝支付对接、微信支付对接、高德地图查询对接等等服务,如果你是一个创业型互联网,大部分可能都是对接别的公司api接口。当你的公司体量上来了时候,这个时候可能有一些公司开始找你进行技术对接了,转变成由你来提供api接口,那这个时候,我们应该如何设计并保证API接口安全呢?
老K博客
2024/12/10
3040
如何保证API接口安全?
拒绝接口裸奔!开放API接口签名验证!
为开发者分配AccessKey(开发者标识,确保唯一)和SecretKey(用于接口加密,确保不易被穷举,生成算法不易被猜测)。
架构师修炼
2020/09/30
1.4K0
安全|API接口安全性设计(防篡改和重复调用)
API接口的安全性主要是为了保证数据不会被篡改和重复调用,实现方案主要围绕Token、时间戳和Sign三个机制展开设计。
黄小怪
2018/12/07
10.5K0
探讨三方接口调用方案设计
三方接口设计是实现系统功能的关键环节。设计一个安全、高效且易于维护的接口调用方案,对于保障系统稳定性、数据安全性和用户体验至关重要。
公众号:码到三十五
2024/11/25
3220
前后端分离 , 如何保证接口安全性 ?
用户使用用户名密码登录后服务器给客户端返回一个Token(通常是UUID),并将Token-UserId以键值对的形式存放在缓存服务器中。服务端接收到请求后进行Token验证,如果Token不存在,说明请求无效。
Jensen_97
2023/07/20
2.8K0
前后端分离 , 如何保证接口安全性 ?
SpringBoot接口设计防篡改和防重放攻击
由于提供给第三方服务调用的 API 接口需要暴露在外网中,并且接口上提供了具体的请求地址和请求参数,那么,接口就有可能被人抓包拦截并对请求参数进行修改后再次发起请求 ,这样一来可能会被盗取信息,二来服务器可能会受到攻击。
程序员皮皮林
2024/11/15
6750
SpringBoot接口设计防篡改和防重放攻击
拒绝接口裸奔!开放API接口签名验证!
为开发者分配AccessKey(开发者标识,确保唯一)和SecretKey(用于接口加密,确保不易被穷举,生成算法不易被猜测)。
java思维导图
2020/09/30
2K0
拒绝接口裸奔!开放API接口签名验证!
十种接口安全方案!!!
日常开发中,如何保证接口数据的安全性呢?接口数据安全的保证过程,主要体现在这几个方面:一个就是数据传输过程中的安全,还有就是数据到达服务端,如何识别数据,最后一点就是数据存储的安全性。介绍下保证接口数据安全的10个方案。
绿毛龟
2024/01/19
1.1K0
十种接口安全方案!!!
API 接口的安全设计验证,我是这么做的!
与前端对接的API接口,如果被第三方抓包并进行恶意篡改参数,可能会导致数据泄露,甚至会被篡改数据,我主要围绕时间戳,token,签名三个部分来保证API接口的安全性
架构师修炼
2021/05/17
1K0
API 接口的安全设计验证,我是这么做的!
Spring Cloud微服务,如何保证对外接口的安全?
通常来说,要将暴露在外网的 API 接口视为安全接口,需要实现防篡改和防重放的功能。
码猿技术专栏
2023/12/31
5540
Spring Cloud微服务,如何保证对外接口的安全?
API接口签名验证,你学废了吗
为开发者分配AccessKey(开发者标识,确保唯一)和SecretKey(用于接口加密,确保不易被穷举,生成算法不易被猜测)。
Java技术精选
2021/08/16
2.8K0
相关推荐
公司来了个大神,三方接口调用方案设计的真优雅~~
更多 >
交个朋友
加入[后端] 腾讯云技术交流站
后端架构设计 高可用系统实现
加入HAI高性能应用服务器交流群
探索HAI应用新境界 共享实践心得
加入行业数字化趋势交流群
解读转型政策方向 参考企业落地案例
换一批
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验