WooCommerce 文档

title: "Store API 接口的限流" post_status: publish comment_status: open taxonomy: category: - woocommerce post_tag: - Store Api - Apis - Repos


Store API 接口的限流

限流 功能现已适用于 Store API 接口。这是一个可选功能,默认情况下是禁用的。可以通过遵循 以下说明 来启用它。

其主要目的是防止对接口的滥用,以及避免因过多的调用而导致运行 Store 的服务器性能下降。

限流跟踪由以下方式控制:用户 ID(已登录用户)、IP 地址(未认证的请求),或者通过过滤器定义的逻辑来识别和分组请求。

它还提供标准的支持,可以在代理、负载均衡器等环境中使用。这也是一个可选功能,默认情况下是禁用的。

UI 控制

目前,此功能只能通过 woocommerce_store_api_rate_limit_options 过滤器进行控制。要通过 UI 进行控制,可以使用以下社区插件:WooCommerce 限流 UI 插件

结账限流

您可以通过以下步骤,在 WooCommerce -> 设置 -> 高级 -> 功能 中启用“限流结账模块和 Store API”,从而为结账页面提交订单和 POST /checkout 接口启用限流。

通过 UI 启用后,限流仅适用于 POST /checkout 接口以及结账模块的提交订单流程。限制为每 60 秒最多 3 个请求。

限制信息

默认情况下,可以在 10 秒的时间范围内最多发出 25 个请求。这些限制可以通过 选项过滤器 进行修改。

受限流影响的方法

POST 请求受到限流的影响。使用 X-HTTP-Method-Override 头部(例如,通过 wp.apiFetch 发送的 PUTPATCH 请求)的请求不受到限流的影响。

限流选项过滤器

提供一个过滤器,用于设置限流选项:

add_filter( 'woocommerce_store_api_rate_limit_options', function() {
    return [
        'enabled' => false, // 启用/禁用限流。默认:false
        'proxy_support' => false, // 启用/禁用代理支持。默认:false
        'limit' => 25, // 每段时间内的请求限制。默认:25
        'seconds' => 10, // 时间范围(秒)。默认:10
    ];
} );

代理标准支持

如果 Store 运行在代理、负载均衡器、缓存服务、CDN 等环境,则支持通过标准 IP 转发头部来按 IP 地址进行限流,这些头部包括:

此功能默认情况下是禁用的。

通过自定义请求指纹启用速率限制

对于更高级的用例,您可以启用基于自定义指纹的速率限制。 这允许自定义实现来分组请求,而无需依赖已登录的用户 ID 或 IP 地址。

自定义基本示例,用于按 User-Agent 和 Accept-Language 组合分组请求

add_filter( 'woocommerce_store_api_rate_limit_id', function() {
    $accept_language = isset( $_SERVER['HTTP_ACCEPT_LANGUAGE'] ) ? sanitize_text_field( wp_unslash( $_SERVER['HTTP_ACCEPT_LANGUAGE'] ) ) : '';

    return md5( wc_get_user_agent() . $accept_language );
} );

限制使用信息的可观察性

当前限制信息可以通过自定义响应头进行观察:

响应头示例

RateLimit-Limit: 5
RateLimit-Remaining: 0
RateLimit-Reset: 1654880642
RateLimit-Retry-After: 28

跟踪限制滥用

这使用了一个修改后的 wc_rate_limit 表,其中添加了一个额外的 remaining 列,用于跟踪在任何给定的请求窗口内的请求计数。 为了便于扩展,实现了一个自定义动作 woocommerce_store_api_rate_limit_exceeded,用于跟踪此类滥用行为。

自定义跟踪使用示例

add_action(
    'woocommerce_store_api_rate_limit_exceeded',
    function ( $offending_ip, $action_id ) { /* 自定义跟踪实现 */ }
);