You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel特定路由限流问题:自定义中间件计数无法自动重置

解决验证邮件路由独立限流问题

问题根源

你使用的自定义中间件存在缓存过期设置错误:Cache::increment 的第三个参数并非过期时间(TTL),导致首次创建缓存时未设置过期规则,计数永久留存,最终触发永久限制。

方案一:修复自定义中间件

修改中间件代码,确保缓存键在创建时正确设置过期时间:

public function handle(Request $request, Closure $next)
{
    $throttle = 5; // 60秒内允许5次请求
    $ttl = 60; // 过期时间60秒
    $key = sprintf('throttle_CustomValidateEmail:%s:%s', $request->ip(), $request->path());

    $currentCount = Cache::get($key, 0);

    if ($currentCount >= $throttle) {
        return abort(429, '请求过于频繁,请稍后再试');
    }

    // 更新计数并设置过期时间,每次请求重置窗口有效期
    Cache::put($key, $currentCount + 1, $ttl);

    return $next($request);
}

如果希望限流窗口从第一次请求开始固定计算(而非每次请求重置),可调整缓存逻辑:

if (!Cache::has($key)) {
    Cache::put($key, 1, $ttl);
} else {
    Cache::increment($key);
}

方案二:使用Laravel自带限流中间件(推荐)

无需自定义中间件,通过扩展Laravel原生throttle中间件,为验证邮件路由生成独立限流键,避免占用全局限流额度:

1. 创建自定义限流中间件

<?php

namespace App\Http\Middleware;

use Illuminate\Routing\Middleware\ThrottleRequests;

class ThrottleVerificationEmails extends ThrottleRequests
{
    /**
     * 生成独立限流键,与全局路由额度隔离
     */
    protected function resolveRequestKey($request)
    {
        // 若用户已登录,可替换为用户ID避免同IP多用户冲突:$request->user()?->id ?? $request->ip()
        return 'throttle:verify-email:' . $request->ip();
    }
}

2. 注册中间件

在app/Http/Kernel.php的$routeMiddleware数组中添加:

protected $routeMiddleware = [
    // ...
    'throttle.verify-email' => \App\Http\Middleware\ThrottleVerificationEmails::class,
];

3. 路由中使用

Route::post('send-verification-email', [VerificationController::class, 'send'])
    ->middleware('throttle.verify-email:5,1');

参数5,1表示:60秒内允许5次请求(格式为请求次数,分钟数)。

补充说明

  • 若用户已登录,建议将用户ID加入限流键,避免同一IP下多用户互相影响
  • 可自定义429响应的提示信息,提升用户体验

内容的提问来源于stack exchange,提问作者Deadman

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 15:00:53