OrchardCore.RateLimits 模块深度指南:多租户请求限流策略的集中管理、四种 Limiter 选型与内置路由限流
CMS后端Web框架【免费下载链接】OrchardCoreOrchard Core is an open-source modular and multi-tenant application framework built with ASP.NET Core, and a content management system (CMS) built on top of that framework.项目地址https://gitcode.com/gh_mirrors/or/OrchardCore点击查看免费下载Orchard Core 的 Rate Limits 模块OrchardCore.RateLimits将 ASP.NET Core 的请求限流能力集中化为每个租户提供可管理的限流策略体系管理员可以在后台以文档形式创建、启停与删除策略在运行时按请求路径前缀或端点分组匹配限流规则并叠加四种内置 LimiterFixed window / Sliding window / Concurrency / Token bucket实现从登录接口保护到租户全局基线的完整防护。读完本文你将掌握该模块的完整概念模型、三种策略作用域的匹配机制、四种 Limiter 的参数语义与选型依据以及如何通过代码注册内置路由/分组限流、使用 Recipe 与部署计划迁移策略。本文以 模块官方文档 为主体并结合仓库源码 OrchardCore.RateLimits.Core 与 OrchardCore.RateLimits 模块 的实现细节进行佐证。模块定位为租户集中化 ASP.NET Core 请求限流Rate Limits 模块的核心职责是集中管理 Orchard Core 租户的 ASP.NET Core 请求限流。启用该功能后它可以应用租户专属的、处于启用状态的限流策略允许管理员编辑已停用策略而无需重载租户通过一次租户重载即可启用或停用一个或多个策略将各功能模块在代码中贡献的命名路由named-route与端点分组endpoint-group限流保持为只读的内置限流始终处于生效状态。从模块注册代码看Startup.cs 在ConfigureServices中调用services.AddRateLimiter()注册 ASP.NET Core 限流中间件基础设施并在Configure中通过app.UseRateLimiter()将其挂入请求管道四种 Limiter 则通过AddKeyedSingletonIRateLimiterSource, ...分别以FixedWindow、SlidingWindow、Concurrency、TokenBucket作为键注册为单例服务。一个值得注意的设计是静态资源被有意排除在限流之外。因为 Orchard 在UseRateLimiter()之前就注册了静态文件中间件脚本、样式表与图片等静态文件请求不会消耗请求预算。这意味着对租户设置的限流额度只作用于动态请求。租户级限流策略Tools - Rate Limits启用模块后后台导航出现Tools工具- Rate Limits菜单由 AdminMenu.cs 提供管理员在此管理租户策略。权限方面由 Permissions.cs 定义对应的权限枚举集中在 RateLimitsPermissions.cs。策略的结构每个策略RateLimitPolicy包含以下要素一个单一可编辑文档——所有策略存放在租户文档 RateLimitPolicyDocument 中其内部只是一个ListRateLimitPolicy Policies一个enabled 标志决定该策略是否在运行时被强制执行一个目标类型作用域Global全局、Endpoint端点或Group分组——对应源码枚举 RateLimitPolicyScope 中的Global 0、Endpoint 1、Group 2一个可选的描述Description所有者与作者元数据OwnerId、Author一个或多个限流器Limiters。策略模型 RateLimitPolicy 还记录了PolicyId、PathEndpoint 策略的路径前缀、GroupNameGroup 策略的分组名、IsEnabled与EnabledUtc最近一次启用时间并带有一个[JsonIgnore]的计算属性StatusRateLimitPolicyStatus用于在 UI 中展示当前启用状态。每个 Limiter 本身是一个 RateLimitLimiter继承自 Orchard 的Entity用Source字段指明解释其属性的 Limiter 来源如FixedWindow具体参数则以实体属性形式内嵌存储。保存、启停与删除的租户重载语义保存已停用的策略直接更新文档不会触发租户重载编辑已启用策略的名称与描述属于元数据修改保存后同样不重载租户启用一个已停用策略 / 停用一个已启用策略 / 删除一个已启用策略会重载租户 shell 一次使生效中的限流配置立即刷新。管理界面能力管理 UI视图位于 Views/Admin提供索引页上的策略搜索行内Enable / Disable快捷操作编辑器仅提供一个 Save 动作当策略处于启用状态时界面给出警告必须先停用或替换该策略才能修改其限流内容批量启用、批量停用、批量删除操作批量动作枚举见 RateLimitPolicyBulkAction.cs。三种策略作用域Global / Endpoint / Group类型匹配对象适用场景Global每个租户请求为所有动态请求施加一个基线预算Endpoint请求路径以配置路径开头的请求保护登录、令牌、注册、API 或 Webhook 路径Group被分配到配置分组的端点在不耦合具体路径的前提下跨相关路由复用同一策略Endpoint 匹配路径前缀Endpoint 策略使用请求路径前缀进行匹配。例如/api可匹配/api、/api/users与/api/orders/42/users/login可匹配/users/login与/users/login/reset若想用单一策略覆盖全部 GraphQL 流量/graphql是很好的选择。Endpoint 策略的路径必须以/开头。这一约束不仅是 UI 层面的提示在 Recipe 导入校验中同样被强制执行见下文 Recipe 一节CreateOrUpdateRateLimitPoliciesStep.cs 中会直接拒绝不以/开头的端点策略。Group 匹配端点元数据Group 策略匹配的是端点元数据endpoint metadata而非请求路径。两种方式可以为端点打上分组标记方式一MVC 控制器或 Action 上使用RateLimitGroupAttribute[RateLimitGroup(authentication, public-api)] public async TaskIActionResult Login(LoginViewModel model) { // ... }方式二Minimal API 或其他端点构建器使用WithRateLimitGroup()/WithRateLimitGroups()endpoints.MapPost(/api/token, HandleTokenAsync) .WithName(Access.Token) .WithRateLimitGroups(authentication, public-api);从源码看RateLimitGroupAttribute 允许AllowMultiple true构造时会对分组名做Trim()去空白、按OrdinalIgnoreCase去重并保证至少有一个非空分组名RateLimitEndpointConventionBuilderExtensions 中的WithRateLimitGroups本质上是把RateLimitGroupAttribute追加到端点元数据集合中。一个端点可以同时属于一个或多个分组。Group 策略有一个对开发者非常友好的特性当没有任何已启用的策略指向该分组时Group 策略不会产生任何效果因此即使在 Rate Limits 功能尚未启用、或租户策略还不存在的情况下提前给端点加上分组元数据也是安全的不会影响正常请求。Limiter 来源Limiter Sources总览每个策略可以包含一个或多个 limiter 来源。当一个已启用的策略命中某请求时该策略上的每一个 limiter 都会被应用多个 limiter 叠加生效。管理 UI 中的Available Limiter Types会为每种 limiter 展示一段简短描述并链接到本文档对应的章节。四种 limiter 来源解决不同的问题Limiter 来源最适合可以理解为FixedWindow简单的每周期上限每 Y 秒只允许 X 个请求SlidingWindow更平滑的节流无生硬的窗口边界在滚动时间范围内允许 X 个请求Concurrency限制并发在途请求同时最多只能有 X 个请求在运行TokenBucket允许突发、但按稳定速率补充的 API一个随时间填充、被请求消耗的桶在模块注册层面这四种来源分别由 FixedWindowRateLimiterSource、SlidingWindowRateLimiterSource.cs、ConcurrencyRateLimiterSource.cs、TokenBucketRateLimiterSource.cs 实现它们继承RateLimiterSourceBaseTData将持久化的参数模型如 FixedWindowRateLimiterData翻译为System.Threading.RateLimiting的RateLimitPartitionstring。以 FixedWindow 为例其分区键格式为{policyName}:{SourceName}:{remoteIp}FixedWindowRateLimiterSource.cs即默认按客户端 IP 分区计数。四种 Limiter 深入解析Fixed window固定窗口当你需要一个明确时间段内的直截了当的硬性上限时使用Fixed window。典型用例允许每60秒内5次密码重置提交允许每5分钟内20次登录尝试应用租户级简单上限如每60秒150个请求。行为特点若限制为10 requests / 60 seconds计数器在下一个窗口边界处重置新窗口一开始客户端即可再次用满全部额度。当简单性比平滑性更重要时选择 Fixed window。Fixed window 参数设置项含义实践指导Permit limit一个完整窗口内允许的请求数。设为10时同一窗口内第 11 个匹配请求会被延迟或拒绝。Window seconds一个窗口持续的时间。60表示每分钟300表示每 5 分钟。Queue limit达到上限后允许额外等待的请求数。希望超限请求立即被拒绝而不是排队等待时使用0。提示Fixed window 通常是最容易让非技术管理员理解的 limiter因为规则读起来很自然每 Y 秒允许 X 个请求。从源码实现看FixedWindowRateLimiterSource.CreatePartition 将PermitLimit、QueueLimit与Window TimeSpan.FromSeconds(WindowSeconds)直接映射到FixedWindowRateLimiterOptions并设置AutoReplenishment true由框架自动按窗口补充额度。其描述文案被生成为{0} requests every {1} seconds, queue limit {2}正好对应每 Y 秒 X 个请求的自然语言。Sliding window滑动窗口当你需要与固定窗口相同的速率上限、但希望窗口边界附近的执行更平滑时使用Sliding window。典型用例登录或验证类端点不希望重置边界附近出现突发公共 API希望节流行为不那么尖锐。行为特点不是一次性全部重置而是把窗口拆分为多个片段segments随着旧片段滚出滚动窗口请求量逐渐过期。当固定窗口显得过于突兀时选择 Sliding window。Sliding window 参数设置项含义实践指导Permit limit完整滚动窗口内允许的请求总数。设为10时Orchard 在整个窗口范围内计数这 10 个请求用完后即触发限流。Window secondsOrchard 回溯计数的窗口长度。60表示回看最近一分钟的流量。Segments per window完整窗口被切分为多少个更小的切片。分段越多恢复越平滑但多数场景4到10已足够。Queue limit达到上限后允许额外等待的请求数。希望立即拒绝而不是让请求等待时使用0。注意Segments per window不会提高限额它只控制旧请求以多快的速度滚出滚动窗口。仓库提供的内置辅助方法 RateLimitPartitionHelpers.CreateSlidingWindowPerIpPolicy 展示了滑动窗口的典型默认参数Window 1 分钟、SegmentsPerWindow 6、QueueLimit 0、AutoReplenishment true并按policyName:remoteIp分区。Concurrency并发当真正的关注点不是一段时间内来了多少请求而是同一时刻有多少昂贵的请求在运行时使用Concurrency。典型用例导出、报表或图像处理端点昂贵的搜索端点调用缓慢下游服务的操作。行为特点若并发上限为3则同一时刻最多只有3个匹配请求在执行其余请求根据队列设置排队或直接拒绝。当需要保护服务器容量或下游依赖免受长耗时请求的拖累时选择 Concurrency。Concurrency 参数设置项含义实践指导Permit limit同一时刻可运行的匹配请求数。设为3时第 4 个请求必须等待或直接失败直到某个运行中的请求结束。Queue limit等待空闲槽位的额外请求数。希望超过实时上限的请求立即失败时使用0。Queue processing order哪个等待中的请求优先获得下一个空闲槽位。Oldest first最早优先是最公平的默认Newest first最新优先在只有最新请求仍有意义时更合适。警告Concurrency不是每分钟请求数而是当前正在运行的请求数。Token bucket令牌桶当你希望在强制可持续平均速率的同时允许短时突发时使用Token bucket。典型用例天然会发送短突发流量的 API 客户端能容忍短暂尖峰、但需要稳定长期上限的 Webhook 接收端偶尔的突发不应被立即阻止的交互式体验。行为特点桶里可能装有20个令牌每个请求消耗一个令牌令牌随时间补充例如每10秒补充5个。当突发容忍度很重要时选择 Token bucket。Token bucket 参数设置项含义实践指导Token limit桶能容纳的最大令牌数。这是客户端能一次性消耗的最大突发量。Tokens per period每个补充周期加回多少令牌。设为5时每个周期桶最多恢复 5 个请求的容量。Replenishment secondsOrchard 多久补充一次桶。10表示每 10 秒补充令牌。Queue limit桶空时允许额外等待的请求数。使用0可立即拒绝超限请求而不是等待补充。Queue processing order等待中的请求谁先获得下一个令牌。Oldest first是最安全的默认Newest first更偏向新请求。用大白话读令牌桶假如你配置Token limit 20Tokens per period 5Replenishment seconds 10那么规则大致是一个客户端最多可以一次性花掉 20 个请求之后每 10 秒最多恢复 5 个请求。选型建议速记如果不确定从 Fixed window 开始当窗口边界效应重要时改用Sliding window当工作时长才是真正的瓶颈时改用Concurrency当需要突发容忍时改用Token bucket。示例策略组合保护登录端点用 Endpoint 策略匹配/Login或你的自定义登录路径再挂一个 fixed-window 或 sliding-window limiter。典型选择Fixed window简单硬性上限Sliding window希望在整个周期内节流更平滑。保护 API 区域用 Endpoint 策略匹配/api并挂载Token bucket可接受短突发时Concurrency每个请求都很昂贵时可选地再加第二个 limiter同时实现突发控制与并发控制多个 limiter 叠加生效。添加租户级基线用Global策略配合 fixed-window limiter让每个动态租户请求共享同一个基线预算。内置路由限流代码贡献的只读策略除了租户文档中的策略各功能模块还可以通过RateLimitsOptions在代码中贡献命名路由限流与分组限流。这些内置限流持续生效并在管理 UI 中以只读条目展示。RateLimitsOptions的完整定义见 RateLimitsOptions.cs其内部用字典保存路由限流RouteRateLimit、用列表保存分组限流GroupRateLimit。命名路由限流示例services.ConfigureRateLimitsOptions(options { options.AddRouteRateLimit( routeName: Login, httpMethod: HttpMethods.Post, partitioner: RateLimitPartitionHelpers.CreateSlidingWindowPerIpPolicy( policyName: password-authentication, permitLimit: 10)); });分组限流示例services.ConfigureRateLimitsOptions(options { options.AddGroupRateLimit( groupName: authentication, partitioner: RateLimitPartitionHelpers.CreateSlidingWindowPerIpPolicy( policyName: shared-authentication, permitLimit: 10)); });匹配规则内置路由限流按以下两个条件匹配路由名称route name以及可选的 HTTP 方法http method。同时匹配两者可以避免共享同一路由名称的GET与POSTaction 意外共享同一个 limiter。从 RateLimitsOptions.cs 的重载可见AddRouteRateLimit支持单方法、多方法IEnumerablestring与不限定方法空集合匹配所有方法三种注册形式内部以routeName或routeName:method1|method2方法按序排后拼接作为字典键去重。内置分组限流按以下条件匹配端点分组名称endpoint group name。若一个端点属于多个分组则每个匹配的内置分组限流与每个匹配的已启用租户分组策略都会与该请求上其余生效的 limiter 合并叠加。首次启用种子化的默认全局策略当功能第一次以策略模型运行时Orchard 会种子化一个已启用的 Default Global Policy使用 fixed-window limiter默认参数为permit limit150window seconds60queue limit0种子过程由迁移Migration触发。模块迁移代码见 GlobalRateLimitsMigrations.cs其引用的种子 Recipe 位于 default-global-policy.recipe.json该 Recipe 使用CreateOrUpdateRateLimitPolicies步骤写入一个PolicyId/Limiter Id由[js: uuid()]生成的策略IsEnabled: true、Scope: GlobalLimiter 的Source为FixedWindow属性FixedWindowRateLimiterData中正是PermitLimit: 150、WindowSeconds: 60、QueueLimit: 0OwnerId与Author分别来自parameters(AdminUserId)与parameters(AdminUsername)。种子完成后租户管理员可以在 UI 中编辑、启用、停用或替换该策略。通过 Recipes 与部署计划迁移策略限流策略可以通过Recipes与**部署计划deployment plans**在租户间迁移Recipe 步骤名称为CreateOrUpdateRateLimitPoliciesRecipe 负载使用policies数组部署 UI 暴露All Rate Limit Policies可导出全部已存储策略Setup 类 Recipe 导出时会用租户管理员参数AdminUserId、AdminUsername填充策略的所有者与作者字段见上方种子 Recipe 中的[js: parameters(...)]用法。初始默认全局策略正是通过模块Migrations文件夹下的迁移 Recipe 种子化的default-global-policy.recipe.json。Recipe 步骤的导入实现是 CreateOrUpdateRateLimitPoliciesStep其中包含值得注意的校验与合并逻辑policies数组为必填缺失会直接报错支持三种作用域未知作用域会被拒绝Endpoint 策略必须定义请求路径且路径必须以/开头Group 策略必须定义分组名导入时按PolicyId或忽略大小写的Name匹配已有策略存在则更新、不存在则创建新创建策略的EnabledUtc会在启用时按需生成。部署端的支持包括部署步骤模型 AllRateLimitPoliciesDeploymentStep、导出源 AllRateLimitPoliciesDeploymentSource以及 UI 驱动器 AllRateLimitPoliciesDeploymentStepDriver。这些服务通过 Startup.cs 中的RecipesStartup需OrchardCore.Recipes.Core功能与DeploymentStartup需OrchardCore.Deployment功能按需注册。安全注意事项限流是一种防御性控制手段有助于在以下高风险端点上减少滥用用户名/密码登录注册密码重置令牌签发双因素验证码的提交或发送公共 API 与 Webhook。这会让攻击者的自动化撞库credential stuffing、暴力破解以及重复的令牌或验证码请求付出更高成本。需要强调的是限流不能替代认证、授权、验证码、账户锁定或监控。应将其与 Orchard Core 和 ASP.NET Core 提供的其他安全功能配合使用构建纵深防御。延伸阅读模块官方文档RateLimits/README.md模块注册与依赖装配src/OrchardCore.Modules/OrchardCore.RateLimits/Startup.cs核心模型策略 RateLimitPolicy、作用域 RateLimitPolicyScope、文档 RateLimitPolicyDocument内置限流配置入口RateLimitsOptions.cs 与分区辅助 RateLimitPartitionHelpers.cs分组标记RateLimitGroupAttribute 与 RateLimitEndpointConventionBuilderExtensions种子策略 Recipedefault-global-policy.recipe.json赞分享CMS后端Web框架【免费下载链接】OrchardCoreOrchard Core is an open-source modular and multi-tenant application framework built with ASP.NET Core, and a content management system (CMS) built on top of that framework.项目地址https://gitcode.com/gh_mirrors/or/OrchardCore点击查看免费下载相关推荐macOS 安装 OpenCV 的实用指南从路线选择到跑通第一张图macOS 安装 OpenCV 的实用指南从路线选择到跑通第一张图 你大概率不是来研究计算机视觉理论的你只是想在 Mac 上尽快处理几张图片、读一段视频然计算机视觉图像处理深度学习机器学习上一篇agentic-awesome-skills 实战指南用 Next.js SaaS 模板快速搭建带订阅计费的 SaaS 产品下一篇React-Bits社区支持如何参与贡献创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
上一篇/下一篇内容由系统自动关联
返回资讯列表 →