客户端限流主要采用手段:纯前端验证码、禁用按钮、调用限制和假排队

一、纯前端验证码
场景
防止机器人或脚本高频提交,需用户完成验证后才能触发请求。

Vue 前端实现

<template>
  <div>
    <button @click="showCaptcha">提交订单</button>
    <div v-if="captchaVisible">
      <img :src="captchaImage" alt="验证码" />
      <input v-model="captchaInput" placeholder="输入验证码" />
      <button @click="verifyCaptcha">验证</button>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      captchaVisible: false,
      captchaImage: "",
      captchaInput: "",
      captchaKey: "", // 后端生成的验证码唯一标识
    };
  },
  methods: {
    async showCaptcha() {
      // 向后端请求验证码
      const res = await this.$axios.get("/api/captcha/generate");
      this.captchaImage = res.data.image;
      this.captchaKey = res.data.key;
      this.captchaVisible = true;
    },
    async verifyCaptcha() {
      // 提交验证码到后端校验
      const res = await this.$axios.post("/api/captcha/verify", {
        key: this.captchaKey,
        code: this.captchaInput,
      });
      if (res.data.success) {
        this.captchaVisible = false;
        this.submitOrder(); // 验证通过后执行实际提交
      }
    },
    submitOrder() {
      // 实际业务请求
      this.$axios.post("/api/order/create");
    },
  },
};
</script>

C# 后端实现

[ApiController]
[Route("api/captcha")]
public class CaptchaController : ControllerBase
{
    private static Dictionary<string, string> _captchas = new Dictionary<string, string>();

    [HttpGet("generate")]
    public IActionResult GenerateCaptcha()
    {
        // 生成随机验证码(示例简化,实际需生成图片)
        var code = new Random().Next(1000, 9999).ToString();
        var key = Guid.NewGuid().ToString();
        _captchas[key] = code;

        return Ok(new 
        {
            key = key,
            image = $"data:image/png;base64,{GenerateBase64Image(code)}" // 生成图片的Base64
        });
    }

    [HttpPost("verify")]
    public IActionResult VerifyCaptcha([FromBody] VerifyRequest request)
    {
        if (_captchas.TryGetValue(request.Key, out var validCode) && validCode == request.Code)
        {
            _captchas.Remove(request.Key);
            return Ok(new { success = true });
        }
        return Ok(new { success = false });
    }
}

二、禁用按钮
场景
防止用户重复点击提交按钮,前端临时禁用按钮。

Vue 前端实现

<template>
  <button 
    @click="handleSubmit" 
    :disabled="isSubmitting"
  >
    {{ isSubmitting ? '提交中...' : '提交订单' }}
  </button>
</template>

<script>
export default {
  data() {
    return {
      isSubmitting: false,
    };
  },
  methods: {
    async handleSubmit() {
      if (this.isSubmitting) return;

      this.isSubmitting = true;
      try {
        await this.$axios.post("/api/order/create");
      } finally {
        this.isSubmitting = false;
      }
    },
  },
};
</script>

三、调用限制(后端频率限制)
场景
限制客户端在固定时间窗口内对同一接口的调用次数。

C# 后端实现(基于内存缓存)

[ApiController]
[Route("api/order")]
public class OrderController : ControllerBase
{
    private static MemoryCache _requestCache = new MemoryCache(new MemoryCacheOptions());
    
    [HttpPost("create")]
    public IActionResult CreateOrder([FromBody] OrderRequest request)
    {
        var clientIp = HttpContext.Connection.RemoteIpAddress.ToString();
        var cacheKey = $"rate_limit_{clientIp}";

        // 检查请求频率(示例:10秒内最多3次)
        if (_requestCache.TryGetValue(cacheKey, out int count) && count >= 3)
        {
            return StatusCode(429, "请求过于频繁,请稍后再试");
        }

        // 更新计数器
        _requestCache.Set(cacheKey, count + 1, TimeSpan.FromSeconds(10));

        // 实际业务逻辑
        return Ok(new { success = true });
    }
}

四、假排队(前端模拟排队)
场景
通过前端动画或提示缓解用户等待焦虑,实际请求仍按正常流程处理。

Vue 前端实现

vue
<template>
  <div>
    <button @click="mockQueue">立即抢购</button>
    <div v-if="isInQueue">
      <p>排队中,前方还有 {{ queuePosition }} 人...</p>
      <div class="loading-animation"></div>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      isInQueue: false,
      queuePosition: 0,
    };
  },
  methods: {
    async mockQueue() {
      if (this.isInQueue) return;

      this.isInQueue = true;
      this.queuePosition = Math.floor(Math.random() * 10) + 1; // 模拟随机队列位置

      // 模拟排队等待(实际请求在后台发送)
      await new Promise(resolve => setTimeout(resolve, 2000));
      
      try {
        await this.$axios.post("/api/purchase");
        this.isInQueue = false;
      } catch (error) {
        this.isInQueue = false;
      }
    },
  },
};
</script>

<style>
.loading-animation {
  width: 20px;
  height: 20px;
  border: 2px solid #ccc;
  border-top-color: #333;
  border-radius: 50%;
  animation: spin 1s linear infinite;
}

@keyframes spin {
  to { transform: rotate(360deg); }
}
</style>

总结与对比
在这里插入图片描述

实际建议:

组合使用:验证码 + 后端限流可有效防御自动化攻击。

用户体验优先:禁用按钮和假排队适合提升用户感知。

监控与告警:结合日志监控异常请求模式(如Nginx或ELK)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值