大佬们对于api并发时防止重复提交有什么好的方案吗?
先限流,再入队列排队,这种呢!~
对于需要及时返回数据的用队列不是太合适把
个人经验,前端按钮限制最方便省事.
接口暴露,直接刷接口了! ^_^
你说这种情况不属于重复提交范围,我理解的重复提交就是接口防止用户网络卡顿或者点击过快导致的重复请求.
前端限流是需要的,但是对于直接刷接口的无效
对于前端用户提交的,前端需要做
对于API接口
如果多次提交每次生成的订单号应该不是唯一的了
并发和重复提交是兩个不同概念吧。
并发不会导致重复提交; 针对多次点击等等的,简单方式是前端限制; 如果是被刷接口,那就要看你的业务性质,是登录用户才能使用还是所有人能使用;
如果登录用户才能使用: 根据UID生成一个form的token,一个UID对应一个token,每次提交都把token重置,然后验证token是否最新的即可。
如果不限制用户的: 根据用户IP地址结合浏览器指纹进行限制,但这种都不是100%解决你的问题,类似的可以参考携程/美团 酒店列表之类的,为了防止爬虫未登录的账号查询都不会返回价格。
那就是在每次提交前先预生成一个唯一token给前端,用于每次提交携带进去验证?
看你实际场景,如果是单纯做API服务的,通过key进行qps限制即可了。 如果你们是被别人趴了接口出来的那种,你可以尝试每个页面的表单生成一个token。提交验证就可以了,但这样只是限制了别人不能同一时间发送相同表单请求
controller之前redis枷锁,处理完就redis解锁
目前我的解决方案就是用redis限制
恩! 我们执勤也是这样做的
csrf token
这个就要看具体使用场景,qps和key限制基本上都能解决,redis无法也是这个原理
这个正好前两天遇到这个问题了,你们api请求有数字签名吗?带时间戳那种计算出来的数字签名,用这个签名做key,然后利用redis的原子计数器,大于1的代表重复请求的,然后抛出异常之类的处理即可
我百度的使用redis锁
//防止重复提交 加redis锁 $key = '_punch_'.$user['id'].'_'.$data['landmark_pk']; $rs = RedisLocal::get_redis(); $ttl = 10; $lock = $rs->set($key, $key, ['nx', 'ex' => $ttl]); if (!$lock) { throw new BaseException(['code' => -1, 'msg' => '请不要频繁提交哦~']); } $res = $this->checkPrize($params); if ($rs->get($key) == $key) { $rs->del($key); }
首先要区分是从用户发起的还是从跨站攻击的; 如果是用户发起的,每个用户都会携带凭证,如JWT、cookie等信息,那么我们可以从业务的角度进行限制,做一些用户级别的api防抖或者限流,如:redis设置一个防抖阈值,总之就是以用户+业务为颗粒度保存一个计数并限制;
我们还可以基于一种约定,设置一些request token,比如md5(query string/http body + timestamp + jwt/session id),保证一次请求一次token;当然这种约定如果是web端,代码很容易被找到,在app上面比较有效;这样的好处是也可以有效防止csrf;
当然从服务端出发,我们还可以基于接口的颗粒度设置一些限流服务,比如使用基于Redis-lua的限流插件;
我的建议是服务端最好把以上三种都实现,同时客户端做好防抖。
公共接口的话,使用一些人机验证组件即可。
访问页面时候生成一个令牌,表单令牌相同提交订单(令牌相同立马删除令牌,然后进行下单流程),失败就提示下单失败。 要不你就加个锁,此时只能有一个锁在执行,拒绝相同请求。
生成令牌也无法保证频繁的调用接口啊
相同提交内容生成相同的签名,同用户标识同签名做分布式锁
幂等
有没有办法不通过redis实现
文件,fopen或者sqlite;但这种只能单机
先限流,再入队列排队,这种呢!~
对于需要及时返回数据的用队列不是太合适把
个人经验,前端按钮限制最方便省事.
接口暴露,直接刷接口了! ^_^
你说这种情况不属于重复提交范围,我理解的重复提交就是接口防止用户网络卡顿或者点击过快导致的重复请求.
前端限流是需要的,但是对于直接刷接口的无效
对于前端用户提交的,前端需要做
对于API接口
如果多次提交每次生成的订单号应该不是唯一的了
并发和重复提交是兩个不同概念吧。
并发不会导致重复提交;
针对多次点击等等的,简单方式是前端限制;
如果是被刷接口,那就要看你的业务性质,是登录用户才能使用还是所有人能使用;
如果登录用户才能使用:
根据UID生成一个form的token,一个UID对应一个token,每次提交都把token重置,然后验证token是否最新的即可。
如果不限制用户的:
根据用户IP地址结合浏览器指纹进行限制,但这种都不是100%解决你的问题,类似的可以参考携程/美团 酒店列表之类的,为了防止爬虫未登录的账号查询都不会返回价格。
那就是在每次提交前先预生成一个唯一token给前端,用于每次提交携带进去验证?
看你实际场景,如果是单纯做API服务的,通过key进行qps限制即可了。
如果你们是被别人趴了接口出来的那种,你可以尝试每个页面的表单生成一个token。提交验证就可以了,但这样只是限制了别人不能同一时间发送相同表单请求
controller之前redis枷锁,处理完就redis解锁
目前我的解决方案就是用redis限制
恩! 我们执勤也是这样做的
csrf token
这个就要看具体使用场景,qps和key限制基本上都能解决,redis无法也是这个原理
这个正好前两天遇到这个问题了,你们api请求有数字签名吗?带时间戳那种计算出来的数字签名,用这个签名做key,然后利用redis的原子计数器,大于1的代表重复请求的,然后抛出异常之类的处理即可
我百度的使用redis锁
首先要区分是从用户发起的还是从跨站攻击的;
如果是用户发起的,每个用户都会携带凭证,如JWT、cookie等信息,那么我们可以从业务的角度进行限制,做一些用户级别的api防抖或者限流,如:redis设置一个防抖阈值,总之就是以用户+业务为颗粒度保存一个计数并限制;
我们还可以基于一种约定,设置一些request token,比如md5(query string/http body + timestamp + jwt/session id),保证一次请求一次token;当然这种约定如果是web端,代码很容易被找到,在app上面比较有效;这样的好处是也可以有效防止csrf;
当然从服务端出发,我们还可以基于接口的颗粒度设置一些限流服务,比如使用基于Redis-lua的限流插件;
我的建议是服务端最好把以上三种都实现,同时客户端做好防抖。
公共接口的话,使用一些人机验证组件即可。
访问页面时候生成一个令牌,表单令牌相同提交订单(令牌相同立马删除令牌,然后进行下单流程),失败就提示下单失败。
要不你就加个锁,此时只能有一个锁在执行,拒绝相同请求。
生成令牌也无法保证频繁的调用接口啊
相同提交内容生成相同的签名,同用户标识同签名做分布式锁
幂等
有没有办法不通过redis实现
文件,fopen或者sqlite;但这种只能单机