为什么要链接动态化,如何动态化

为了避免F12或着抓包获取到秒杀链接然后通过不正当手段自动化秒杀,下面我们将接口路径进行动态生成,只有当点击秒杀按钮时才能成功验证。用户在下单前,先发出一个生成Md5 hash值的请求,根据抢购商品id和用户IdMd5加密算法和随机盐生成一个hash值存到redis中,在redis中设置过期时间,等用户真正下单时发起的下单请求(秒杀请求)携带着Md5hash值和redis中已经存在的hash值作比较是否相等,就能判断此请求是根据脚本发起的请求(没有点击抢购秒杀按钮)还是用户在软件下的单了,避免一些用户的脚本抢购。该业务流程可以应用到任意系统。

当用户点击秒杀按钮时,此时去异步获取秒杀path

function getMiaoshaPath() {
        var good_id = $("#good_id").val();
        $.ajax({
            url: "/getmiaoshapath",
            type: "GET",
            data:{
                good_id : good_id
            },
            success:function (data) {
                if(data.code == 0){
                    miaosha(data.data);
                }else{
                    alert(data.msg)
                }
            },
            error:function () {
                alert("服务端请求错误")
            }
        })
    }
@RequestMapping("/getmiaoshapath")
    @ResponseBody
    public Result<String> getMiaoshaPath(@UserParameter User user,@RequestParam("good_id") int good_id){
        if(user == null){
            return Result.error(CodeMsg.SESSION_ERROR);
        }
        String pathUUID = Md5Utils.md5(UUIDUtil.uuid()+"miaoshadizhi");
        redisService.set(MiaoShaKey.miaoShaPathKey,user.getId()+":"+good_id,pathUUID);
        return Result.success(pathUUID);
    }

获取到服务端生成的path之后传递给秒杀接口进行校验,相等则通过

    @RequestMapping("/miaosha_static/{path}")
    @ResponseBody
    public Result<Integer> miaoSha_static(@RequestParam("good_id") int good_id,
                                          @UserParameter User user,
                                          @PathVariable("path") String path){
        //验证path是否正确
        boolean isPathCorrect = miaoShaService.checkPath(user, good_id, path);
        if(!isPathCorrect){
            return Result.error(CodeMsg.SERVER_ERROR);
        }

        System.out.println("good_id"+good_id+"---"+"user"+":"+user);
        //库存标记,如果库存小于零则直接结束,不操作redis
        if(isOver.get(good_id)){
            return Result.error(CodeMsg.OUT_OF_STOCK);
        }

        //判断是否还有库存
        //预减库存
        Long decr = redisService.decr(GoodListKey.miaoshaGoodCountKey, good_id + "");
        if(decr < 0){
            isOver.put(good_id,true);
            return Result.error(CodeMsg.OUT_OF_STOCK);
        }

        //判断该用户是第一次秒杀,不可重复秒杀
        //查找redis缓存,绕开数据库
        Miaosha_order miaosha_order = redisService.get(MiaoSha_OrderKey.orderKey,user.getId()+":"+good_id,Miaosha_order.class);
        if(miaosha_order != null){
            return Result.error(CodeMsg.NO_REPEAT_MIAOSHA);
        }

        MiaoshaMsg msg = new MiaoshaMsg();
        msg.setUser(user);
        msg.setGood_id(good_id);
        //秒杀入队
        provider.miaoshaProvider(msg);
        return Result.success(0);  //0代表排队中
    }
public boolean checkPath(User user,long good_id,String path){
        String s = redisService.get(MiaoShaKey.miaoShaPathKey, user.getId() + ":" + good_id, String.class);
        return path.equals(s);
    }
最后修改:2021 年 11 月 15 日
如果觉得我的文章对你有用,请随意赞赏