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

如何在NestJS中结合Redis实现IP与请求体速率限制

实现NestJS多维度速率限制(IP+请求体字段)

问题分析

你当前的配置仅启用了单一维度的速率限制(默认按IP校验),触发限流后会拦截所有请求,无法同时实现IP和请求体字段(如用户名)两个维度的校验——只要任一维度达到阈值就返回429。

正确实现步骤

1. 自定义ThrottlerGuard

重写handleRequest方法,同时生成IP和请求体字段的限流标识,分别校验两个维度的请求次数,任一维度超标就触发429。

// src/common/guards/multi-throttler.guard.ts
import { ThrottlerGuard } from '@nestjs/throttler';
import { ExecutionContext, Injectable } from '@nestjs/common';

@Injectable()
export class MultiThrottlerGuard extends ThrottlerGuard {
  async handleRequest(context: ExecutionContext, limit: number, ttl: number): Promise<boolean> {
    const request = context.switchToHttp().getRequest();
    
    // 生成IP维度的限流标识
    const ipTracker = this.getTracker(request);
    // 生成请求体用户名维度的限流标识(根据实际字段名调整)
    const usernameTracker = request.body?.username ? `username:${request.body.username}` : null;

    // 校验IP维度限流
    const ipRequestCount = await this.storage.increment(ipTracker, ttl);
    if (ipRequestCount > limit) {
      return false;
    }

    // 校验用户名维度限流(存在用户名时才校验)
    if (usernameTracker) {
      const usernameRequestCount = await this.storage.increment(usernameTracker, ttl);
      if (usernameRequestCount > limit) {
        return false;
      }
    }

    return true;
  }
}

2. 替换全局Guard配置

在对应的业务Module中,把默认的ThrottlerGuard替换为自定义的多维度Guard:

// 对应业务Module.ts
import { APP_GUARD } from '@nestjs/core';
import { MultiThrottlerGuard } from './common/guards/multi-throttler.guard';

@Module({
  providers: [
    {
      provide: APP_GUARD,
      useClass: MultiThrottlerGuard,
    },
  ],
})
export class YourBusinessModule {}

3. 调整ThrottlerModule全局配置

保留Redis存储配置,可根据需求设置全局默认的限流参数,也能在控制器上通过注解覆盖:

// app.module.ts
import { ThrottlerModule } from '@nestjs/throttler';
import { ThrottlerStorageRedisService } from 'nestjs-throttler-storage-redis';
import Redis from 'ioredis';

@Module({
  imports: [
    ThrottlerModule.forRoot({
      ttl: Number(process.env.IP_VELOCITY_TTL) || 86400, // 默认24小时(秒)
      limit: Number(process.env.IP_VELOCITY_COUNT) || 100, // 默认单维度请求次数
      storage: new ThrottlerStorageRedisService(new Redis({
        host: process.env.REDIS_HOST || 'localhost',
        port: Number(process.env.REDIS_PORT) || 6379,
        // 可添加Redis密码、数据库等配置
      })),
    }),
  ],
})
export class AppModule {}

4. 控制器路由配置

在需要限流的路由上,用@Throttle注解设置该路由的专属限流规则:

// controller.ts
import { Throttle } from '@nestjs/throttler';
import { Controller, Post, Body } from '@nestjs/common';

@Controller('auth')
export class AuthController {
  @Post('login')
  @Throttle(3, 3600) // 1小时内,IP或用户名维度最多请求3次
  async login(@Body() loginDto: { username: string; password: string }) {
    // 登录业务逻辑
    return { message: '登录成功' };
  }
}

关键说明

  • 两个维度的限流标识相互独立,分别存储在Redis中,互不干扰
  • 只要IP或用户名任一维度的请求次数超过设定阈值,就会返回429错误
  • 如果请求体中无目标字段(如部分公共接口),仅会校验IP维度的限流

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 13:15:27