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

Laravel无认证开放API限流:同IP网络设备冲突解决方法

无认证开放API的Laravel限流替代方案(解决共享IP问题)

针对无认证开放API遇到的同一网络共享IP导致的限流误判问题,以下是几种可落地的替代方案:

1. Cookie会话标识限流

给首次访问的客户端分配唯一Cookie标识,以此作为限流依据。同一网络下不同设备的Cookie相互独立,能有效区分请求来源。

实现示例

<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Support\Str;
use Illuminate\Http\Request;

class ApiRateLimit
{
    public function handle(Request $request, Closure $next)
    {
        // 获取或生成会话标识
        $sessionId = $request->cookie('api_session_id');
        if (!$sessionId) {
            $sessionId = Str::uuid()->toString();
            $response = $next($request);
            // 设置有效期1天的Cookie
            return $response->cookie('api_session_id', $sessionId, 1440);
        }

        // Redis限流逻辑
        $redis = app('redis')->connection();
        $limitKey = "rate_limit:api:{$sessionId}";
        $maxAttempts = 100; // 1分钟内最多100次请求
        $decaySeconds = 60;

        $currentAttempts = $redis->incr($limitKey);
        if ($currentAttempts > $maxAttempts) {
            // 首次超限设置过期时间
            if ($redis->ttl($limitKey) === -1) {
                $redis->expire($limitKey, $decaySeconds);
            }
            return response()->json(['message' => '请求过于频繁,请稍后再试'], 429);
        }

        // 首次请求设置过期时间
        if ($currentAttempts === 1) {
            $redis->expire($limitKey, $decaySeconds);
        }

        return $next($request);
    }
}

注意事项

  • 需处理客户端禁用Cookie的情况,可降级为IP限流,或提示用户启用Cookie。
  • Cookie标识存在被伪造的可能,若API安全性要求高,可结合IP做双重验证。

2. 自定义请求头设备标识限流

如果API面向可控客户端(如自研APP),可要求客户端在请求头中携带设备唯一标识(如IMEI、设备UUID),以此作为限流键。

实现示例

<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;

class ApiRateLimit
{
    public function handle(Request $request, Closure $next)
    {
        $deviceId = $request->header('X-Device-ID');
        if (!$deviceId) {
            return response()->json(['message' => '缺少必要的设备标识'], 400);
        }

        $redis = app('redis')->connection();
        $limitKey = "rate_limit:api:{$deviceId}";
        $maxAttempts = 100;
        $decaySeconds = 60;

        $currentAttempts = $redis->incr($limitKey);
        if ($currentAttempts > $maxAttempts) {
            if ($redis->ttl($limitKey) === -1) {
                $redis->expire($limitKey, $decaySeconds);
            }
            return response()->json(['message' => '请求过于频繁,请稍后再试'], 429);
        }

        if ($currentAttempts === 1) {
            $redis->expire($limitKey, $decaySeconds);
        }

        return $next($request);
    }
}

注意事项

  • 第三方不可控客户端可能伪造设备ID,可结合IP+设备ID组合作为限流键,提升安全性。

3. IP+User-Agent组合限流

将客户端IP与User-Agent信息组合后哈希,作为限流标识。同一网络下不同设备的User-Agent通常存在差异,能在不增加用户操作成本的前提下提升限流精准度。

实现示例

<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;

class ApiRateLimit
{
    public function handle(Request $request, Closure $next)
    {
        $ip = $request->ip();
        $userAgent = $request->header('User-Agent') ?? '';
        // 哈希组合值避免过长
        $identifier = md5($ip . $userAgent);

        $redis = app('redis')->connection();
        $limitKey = "rate_limit:api:{$identifier}";
        $maxAttempts = 100;
        $decaySeconds = 60;

        $currentAttempts = $redis->incr($limitKey);
        if ($currentAttempts > $maxAttempts) {
            if ($redis->ttl($limitKey) === -1) {
                $redis->expire($limitKey, $decaySeconds);
            }
            return response()->json(['message' => '请求过于频繁,请稍后再试'], 429);
        }

        if ($currentAttempts === 1) {
            $redis->expire($limitKey, $decaySeconds);
        }

        return $next($request);
    }
}

注意事项

  • 若同一网络下设备使用完全相同的客户端(如同一版本的浏览器),仍可能出现限流冲突,但比单纯IP限流的情况好很多。

4. 验证码驱动的临时令牌限流

对于高频请求的核心接口,可要求用户先完成验证码验证(图形/短信),验证通过后生成临时令牌,后续请求用该令牌做限流标识。这种方式能彻底区分真实用户,但会增加用户操作成本。

核心逻辑

  1. 首次请求接口时,返回验证码要求;
  2. 用户提交验证码验证通过后,生成唯一令牌并存入Redis,设置有效期(如1小时);
  3. 后续请求携带令牌,以令牌为标识执行限流;
  4. 令牌过期后,重新要求用户验证。

内容的提问来源于stack exchange,提问作者adithyan.cs

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 13:20:46