今天面试被人问到一个幂等性问题,求大家解惑

2020-08-27 17:04:20 +08:00
 xiaofan2

他说的是如果一个人不小心点击两次,生成不同请求如何保证幂等?两次不同请求代表 token 不同或者前端发送的随机数不同,那如何防止??

6540 次点击
所在节点    程序员
29 条回复
676529483
2020-08-27 17:10:25 +08:00
如果两次点击是误操作,那用一些全局唯一的标识就可以了,比如 uuid 之类的,后端来判断是不是同一次页面的;
如果是想要防止业务点击多次,那就要业务 参数来幂等了,比如订单号
lyog
2020-08-27 17:12:34 +08:00
如果是我,我会用个分布式锁,然后再加插前查询
coderxy
2020-08-27 17:13:49 +08:00
1.首先看什么样的接口,如果是 get 请求啥的天然幂等,不需要另外处理
2.一般这种场景,前端会设计冷却锁。即一个按钮点击后除非请求结果返回或者过了多长时间,才会再次发起请求
3.如果前端无法控制,那么可以在接口设计上考虑。比如如果是创建一个资源,可以在后端加上并发锁,一个用户只能有一个创建动作在执行,其它请求排队。

总的来说方案很多,还是要根据实际场景设计。
takemeaway
2020-08-27 17:14:01 +08:00
先前端限制不能点两次,方法很多。
后端再用唯一值和事务限制一下就行了。
lidlesseye11
2020-08-27 17:24:32 +08:00
个人觉得幂等性是业务设计问题,不是技术问题吧。。
两次请求都不同了凭啥要幂等?
garlics
2020-08-27 17:27:31 +08:00
带上 csrf token ?
ylsc633
2020-08-27 17:31:12 +08:00
1. web 常见的就是 csrf token
2. 前端按钮限制仅点击一次
3. 每个提交地址带个随机参数,用完即废
4. 数据做幂等插入
5.etc.
lipcao
2020-08-27 17:31:24 +08:00
以前做过 aop+redis 锁 防止表单重复提交,但是也是基于 token 来做的,token 都不一样了 不是两次不同的请求吗?一个页面里面存了两个 token ?没看明白
Evilk
2020-08-27 17:45:42 +08:00
@lidlesseye11 同问
wysnylc
2020-08-27 17:53:26 +08:00
yangbonis
2020-08-27 18:55:01 +08:00
信息安全 重放攻击?
zjsxwc
2020-08-27 19:05:39 +08:00
get 请求不影响;
post 请求看业务,有些需求本来不就是幂等的(大部分 post 请求都是),有些需求天生就不能重复(比如需要短信验证码的场景,验证码用过之后里面失效了),有些需求业务上就需要判断是否重复发起(如果检查到重复发起忽略后续处理但返回成功就是幂等,如果检查到重复发起直接报错返回失败就不是幂等)。
Jooooooooo
2020-08-27 19:05:54 +08:00
前端拦住

不过业务上两次不同的请求为啥要防止

这个最终想问的是如何判断是两次有效请求还是一次?
guagusi
2020-08-27 20:01:40 +08:00
以下单为例,1>用户进入下单页面先请求一个唯一的订单 token ; 2>用户点击下单后,带上 token 提交,下单按钮置灰不可点击; 3>后端校验 token 是否重复; 4>增加同一用户两次请求频率的限制,例如 1s 内多次下单;
leeg810312
2020-08-27 21:34:04 +08:00
问题改成误提交 2 次,怎样保证业务数据唯一性或最终一致性,这样比较准确?防君子只要前端控制,在提交后禁用提交按钮即可。防小人,就是阻挡重放攻击,那么上面很多人已经回答了。
oneisall8955
2020-08-27 22:15:33 +08:00
1.实现幂等性常见的方式有:悲观锁( for update )、乐观锁、唯一约束
2.几种方式,按照最优排序:乐观锁 > 唯一约束 > 悲观锁
摘抄自网络,我面试时候也是这么回答的
npe
2020-08-27 22:19:16 +08:00
幂等跟原子性、一致性感觉差不多。
laminux29
2020-08-27 22:37:16 +08:00
这事一定要和业务一起考虑。

举几个场景:

1.需要支持快速多次点击的场景:比如点外卖,或者淘宝下单,有时候需要快速多次点击增加数量按钮。

2.需要禁止快速多次点击的场景:比如提交订单按钮,按一次就够了。多按属于业务上的无效操作。

3.只允许慢速多次点击的场景:比如视频网站的发送弹幕按钮。

4.只允许慢速单次点击的场景:比如在线考试的多选题。
opengps
2020-08-27 22:37:16 +08:00
保存不成功,客户端的 requestid 不能重新 new
lihongming
2020-08-28 01:09:38 +08:00
要保证幂等性,你总得有一个唯一识别来区分不同的请求。所以你首先得定义唯一识别,比如订单可以用订单号(防止重复支付),帖子可以用内容(比如很多论坛程序不允许连发两个一模一样的帖子),什么都没有的可以用 token 等等。

如果真像楼主说的两次请求有不同的 token,那是后端设计的问题,前端只能用 js 控制一下重复提交,不可能完全禁止。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/701963

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX