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

如何防范基于Laravel v11 Livewire的结账系统遭BIN攻击?

防范BIN攻击的解决方案(基于Laravel+Livewire+Stripe)

一、请求限流:拦截高频重复请求

利用Laravel原生限流功能,针对IP、邮箱等维度限制请求频率,在支付初始化前拦截恶意高频请求。

实现步骤:

  1. 在Livewire组件中引入限流门面:
use Illuminate\Support\Facades\RateLimiter;
  1. 在initializePayment方法开头添加限流逻辑:
public function initializePayment()
{
    // IP维度限流:1分钟内最多5次请求
    $ipKey = 'checkout:'.$this->getClientIp();
    if (!RateLimiter::attempt($ipKey, 5)) {
        $this->addError('rate_limit', '请求过于频繁,请1分钟后再试');
        return;
    }

    // 邮箱维度限流(若用户已提供邮箱)
    if (!empty($this->email)) {
        $emailKey = 'checkout:email:'.$this->email;
        if (!RateLimiter::attempt($emailKey, 3)) {
            $this->addError('rate_limit_email', '该邮箱请求过于频繁,请稍后再试');
            return;
        }
    }

    // 原有支付逻辑...
}
  1. 新增获取客户端IP的方法:
private function getClientIp()
{
    return request()->ip();
}

二、验证码验证:区分人机访问

当检测到可疑行为(如支付失败次数超标)时,强制要求用户完成验证码验证,拦截机器人攻击。

实现步骤:

  1. 安装并配置验证码包(如mews/captcha),在Livewire组件中添加验证码字段:
public $captcha;
  1. 更新组件验证规则:
protected $rules = [
    // 原有字段验证规则...
    'captcha' => 'required|captcha',
];
  1. 在结账模板中添加验证码输入区域:
<div>
    <label>验证码</label>
    <input type="text" wire:model="captcha">
    <img src="{{ captcha_src() }}" onclick="this.src='{{ captcha_src() }}?' + Math.random()">
    @error('captcha') <span class="text-red-500">{{ $message }}</span> @enderror
</div>
  1. 在支付初始化方法中添加验证码校验逻辑:
public function initializePayment()
{
    $ip = $this->getClientIp();
    $failureCount = Redis::get('checkout:failures:'.$ip) ?? 0;

    // 失败次数超过3次时验证验证码
    if ($failureCount >= 3) {
        $this->validate(['captcha' => 'required|captcha']);
    }

    // 原有限流、支付逻辑...
}

三、可疑活动记录与拦截

通过Redis记录IP、邮箱的支付失败次数,达到阈值后直接拦截请求。

实现步骤:

  1. 在Stripe支付失败回调(取消页面或Webhook)中记录失败次数:
public function handlePaymentFailure($sessionId)
{
    $stripe = new StripeClient(env('STRIPE_SECRET'));
    $session = $stripe->checkout->sessions->retrieve($sessionId);
    
    $ip = request()->ip();
    // 记录IP失败次数,有效期1小时
    Redis::incr('checkout:failures:'.$ip);
    Redis::expire('checkout:failures:'.$ip, 3600);

    // 记录邮箱失败次数(若存在)
    if ($session->customer_email) {
        Redis::incr('checkout:failures:email:'.$session->customer_email);
        Redis::expire('checkout:failures:email:'.$session->customer_email, 3600);
    }
}
  1. 在支付初始化方法中添加失败次数检查:
public function initializePayment()
{
    $ip = $this->getClientIp();
    $failureCount = Redis::get('checkout:failures:'.$ip) ?? 0;

    // 失败次数超过5次时直接拦截
    if ($failureCount >= 5) {
        $this->addError('blocked', '该IP存在异常支付行为,请1小时后再试');
        return;
    }

    // 原有限流、验证码逻辑...
}

四、Stripe层面防护

利用Stripe原生功能减少攻击影响:

  • 启用Stripe Radar:配置自定义规则拦截同一BIN的多次失败尝试,自动识别欺诈交易
  • 启用支付方法验证:在创建支付会话前验证卡片有效性,减少无效请求传递到支付网关
  • 配置Webhook:实时监听支付失败事件,及时更新本地失败次数记录

五、优化后的完整initializePayment示例

use Illuminate\Support\Facades\RateLimiter;
use Illuminate\Support\Facades\Redis;

public function initializePayment()
{
    $ip = $this->getClientIp();
    $failureCount = Redis::get('checkout:failures:'.$ip) ?? 0;

    // 1. 拦截异常IP
    if ($failureCount >= 5) {
        $this->addError('blocked', '该IP存在异常支付行为,请1小时后再试');
        return;
    }

    // 2. IP维度限流
    $ipKey = 'checkout:'.$ip;
    if (!RateLimiter::attempt($ipKey, 5)) {
        $this->addError('rate_limit', '请求过于频繁,请1分钟后再试');
        return;
    }

    // 3. 邮箱维度限流
    if (!empty($this->email)) {
        $emailKey = 'checkout:email:'.$this->email;
        if (!RateLimiter::attempt($emailKey, 3)) {
            $this->addError('rate_limit_email', '该邮箱请求过于频繁,请稍后再试');
            return;
        }
    }

    // 4. 验证码校验(失败次数超标时)
    if ($failureCount >= 3) {
        $this->validate(['captcha' => 'required|captcha']);
    }

    // 原有支付逻辑
    $application = Application::findOrFail($this->applicationId);
    $stripe = new StripeClient(env('STRIPE_SECRET'));

    $lineItem = [
        [
            'price_data' => [
                'currency' => 'usd',
                'product_data' => [
                    'name' => 'Test Name',
                    'description' => "Description",
                    'images' => [asset('assets/images/1.jpeg')],
                ],
                'unit_amount' => 49 * 100,
            ],
            'quantity' => 1,
        ],
    ];

    $stripeSession = $stripe->checkout->sessions->create([
        'payment_method_types' => ['card'],
        'line_items' => $lineItem,
        'mode' => 'payment',
        'metadata' => [
            'application_id' => $application->id,
            'application_number' => $application->application_number,
        ],
        'customer_email' => $this->email,
        'payment_intent_data' => [
            'description' => "Payment for Application #{$application->application_number}",
            'metadata' => [
                'application_id' => $application->id,
                'application_number' => $application->application_number,
                'email' => $this->email,
                'phone' => $this->phone_number,
                'first_name' => $this->first_name,
                'last_name' => $this->last_name,
            ],
        ],
        'success_url' => route('stripe.success', [], true) . '?session_id={CHECKOUT_SESSION_ID}',
        'cancel_url' => route('stripe.cancel', [], true) . '?session_id={CHECKOUT_SESSION_ID}',
    ]);

    return redirect()->away($stripeSession->url);
}

private function getClientIp()
{
    return request()->ip();
}

内容的提问来源于stack exchange,提问作者inżynier umair

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 03:02:16