首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >多个请求同时绕过检查。

多个请求同时绕过检查。
EN

Stack Overflow用户
提问于 2018-05-27 22:14:53
回答 1查看 653关注 0票数 1

基本上,我有一个由PHP (Laravel)构建的在线游戏。它的功能非常简单。当玩家装备一个物品时,它会检查是否同一类型的物品已经装备好了。如果没有相同类型的装备,它就会继续进行装备。

这是通过简单地将库存模型上装备的旗子设置为1来完成的。

代码语言:javascript
复制
        if($alreadyequippeditem == false){
        //equip current item
        $inventory = \App\Inventory::find($item->pivot->id);
        $inventory->equipped = 1;
        $inventory->save();
        }

然而,如果一个人做得足够快,一个人可以同时装备两个(甚至更多)物品。根本上绕过了支票。

在我看来,这两个请求完全是由服务器同时处理的,它们在完全同时装备这些项,并且基本上绕过了检查。这可能解释了为什么两个项目可以装备,因为在请求运行时,它们不承认对方。我可能错了,但这是我唯一能想到的解释。

我怎么才能避开这一切?是否有办法限制它,以便同时只发送一个请求?我不记得当我用核心PHP和没有框架构建系统时遇到过这个问题,所以我不知道这是否是由laravel配置引起的。我知道我可能可以使用队列来绕过它(虽然我还没有深入研究它),但是我更愿意找到一个在站点范围内工作的解决方案,因为这个特定的问题影响到系统的许多领域。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-05-27 23:20:22

问题(种族状况)

你所经历的是一个经典的种族条件教科书的例子

竞争条件是当设备或系统试图同时执行两个或多个操作时发生的不良情况,但由于设备或系统的性质,操作必须按照正确的顺序进行。

示例修复了所有基本要素

幸运的是,这不是一个新问题,也不是一个很难解决的问题。特别是在使用Laravel时:

代码语言:javascript
复制
<?php
namespace App\Http\Controllers;

use App\Http\Controllers\Controller;
use App\Inventory;
use App\Player;
use Request;


class BustRaceConditionsController extends Controller
{
    public function EquipItem(Request $request)
    {
        \DB::beginTransaction();

        $player = $player->where("id", $request->user()->player_id)->lockForUpdate()->first();

        $success = true;

        try {

            /* some logic here to check if item is equiped or not */

            if (itemIsEquiped()) {

                $success = false;

            } else {

                /* lets equip the item, then save it, and then we need to commit it to the DB */

                $player->itemEquip = $item;
                $player->save();

                \DB::commit();

            }


        } catch (\Exception $e) {

            $success = false;
            \DB::rollback();

        }
        return ['success' => $success];
    }
}
  1. 这是一个非常粗糙的例子,说明了在Laravel中是如何做到的,但本质上,这里发生的事情是我们启动了一个DB事务,它允许我们从根本上确保一切正常工作,否则什么都不做。在这种情况下,这一点特别有用。
  2. 接下来,我们从模型中获取我们想要的所有数据,但请注意,我在方法链中使用了lockForUpdate()。这是为了确保在我的更改提交或失败之前,其他任何东西都不能读写,从而释放锁。
  3. 最后,我们需要将更改提交到DB,或者最终失败并回滚所有更改。

我希望这能帮到你!

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/50556992

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档