我目前正在开发一个在线课程系统,学生可以在该系统中选择任何课程并注册。该课程将以一对一的原则进行,因此学生将选择某个课程日期,并在该日期与讲师进行在线视频会议。每节课程只有一名讲师和一名学生。典型的用例流程是:
- 学生出版社"注册";按钮,然后转到下一页
- 在此页面上,学生从日历中选择课程日期(仅从可用日期中选择(,然后进入结账页面
- 在结账页面上,学生输入他/她的卡详细信息和向学生收取的一定金额
在这种情况下可能会出现比赛情况(假设只有2名用户和1名教练(:
- User1从日历中选择日期并进入结账页面
- 同时,User2也选择了完全相同的日期并进入结账页面
- User2比User1更快地输入卡详细信息,并保留该日期
- User1输入卡详细信息,系统向学生和BINGO收费(同一日期有两名学生(
我不想在付款前检查日期可用性,所以我认为这会给用户带来不好的体验,所以用户必须再次转到上一步并选择另一个日期。即使这样也可能无限发生:(
任何想法都将受到欢迎。此外,我可以更改当前的注册流程以保护安全。
您要查看的参考文献是Pat Helland 2007:回忆、猜测和道歉
您有一个分布式系统,远程客户端正在查看可能过期的数据的本地副本。因此,您的协议需要认识到,您将收到有关基于过时数据的决策的消息,并明确处理当前无法获得所需决策结果的意外情况。
REST部分是";只是";为您的协议提供正确的启示。
对协议的一个可能的改变是引入临时搁置的想法,这可能会有所帮助;Alice暂时保留了该时隙,因此当Bob询问该时隙不可用时,但如果Alice拒绝行使该选项,该时隙可能会在稍后变为可用。
(这并不能消除比赛条件,当然,它只是移动它(。
这里的一个常见协议解决方案是超额预订-您在时隙上接受两个声明,然后稍后清理混乱。
商业航空公司总是做这种事情;他们希望每次航班的利润最大化,这意味着卖出的机票比飞机上的座位还多。他们可以做到这一点,因为有足够多的旅行者后来改变了他们的计划,从而有了有效的盈余。
但有时,同一航班上出现了太多付费客户,然后应急计划出台了——候补乘客被推迟,持票客户因更改计划而获得补偿,等等
无论如何,你可能需要应急协议(如果教练不得不取消预约,例如因为生病,会发生什么(;预订期间的比赛条件只是添加到跑步记录中的又一个应急协议。
在确定了应急协议应该是什么之后,您还有第二个问题需要探索:该协议的哪些部分应该是自动化的。如果冲突很少发生,那么将问题升级给人类来解决可能是有意义的,而不是在代码中这样做。有时,正确的答案是让机器不要挡道。
我想实现双重检查机制,所以:
- 当User1进入日历页面时,它将创建与服务器(SSE或WebSocket(的持久连接。可用日期将实时显示。因此,当User1选择任何日期并进行结账时,将发布一个事件,该日期将被标记为BLOCKED,直到付款完成
- 当用户1输入他的卡详细信息并单击"支付"按钮时,系统将再次检查该日期是否真的由用户1保留
- 如果付款成功,此日期将从BLOCKED更新为RESERVED
但考虑到这是一个带有React客户端的REST API,所有端点对任何人都是可见的。因此,攻击者可以使用简单的暴力来阻止课程的所有可用日期。