wp_check_comment_flood()
云策文档标注
概述
wp_check_comment_flood() 函数用于检测评论是否发生洪水攻击(即短时间内大量评论)。该函数不会对具有管理或审核权限的用户执行检查,以避免阻塞管理员操作。
关键要点
- 函数检查评论是否在短时间内频繁发布,基于IP地址、邮箱和最近一小时内的评论记录。
- 如果检测到洪水攻击,默认会调用 wp_die() 终止执行并显示错误消息,但可通过 $avoid_die 参数控制行为。
- 支持多个过滤器(如 comment_flood_filter 和 comment_flood_message)和动作(如 comment_flood_trigger)来自定义洪水检测逻辑和错误消息。
- 函数返回布尔值,表示是否发生评论洪水攻击。
代码示例
function wp_check_comment_flood( $is_flood, $ip, $email, $date, $avoid_die = false ) {
global $wpdb;
// Another callback has declared a flood. Trust it.
if ( true === $is_flood ) {
return $is_flood;
}
// Don't throttle admins or moderators.
if ( current_user_can( 'manage_options' ) || current_user_can( 'moderate_comments' ) ) {
return false;
}
$hour_ago = gmdate( 'Y-m-d H:i:s', time() - HOUR_IN_SECONDS );
if ( is_user_logged_in() ) {
$user = get_current_user_id();
$check_column = '`user_id`';
} else {
$user = $ip;
$check_column = '`comment_author_IP`';
}
$sql = $wpdb->prepare(
"SELECT `comment_date_gmt` FROM `$wpdb->comments` WHERE `comment_date_gmt` >= %s AND ( $check_column = %s OR `comment_author_email` = %s ) ORDER BY `comment_date_gmt` DESC LIMIT 1",
$hour_ago,
$user,
$email
);
$lasttime = $wpdb->get_var( $sql );
if ( $lasttime ) {
$time_lastcomment = mysql2date( 'U', $lasttime, false );
$time_newcomment = mysql2date( 'U', $date, false );
$flood_die = apply_filters( 'comment_flood_filter', false, $time_lastcomment, $time_newcomment );
if ( $flood_die ) {
do_action( 'comment_flood_trigger', $time_lastcomment, $time_newcomment );
if ( $avoid_die ) {
return true;
} else {
$comment_flood_message = apply_filters( 'comment_flood_message', __( 'You are posting comments too quickly. Slow down.' ) );
if ( wp_doing_ajax() ) {
die( $comment_flood_message );
}
wp_die( $comment_flood_message, 429 );
}
}
}
return false;
}注意事项
- 函数参数包括 $is_flood(布尔值,表示是否已检测到洪水)、$ip(评论者IP地址)、$email(评论者邮箱)、$date(MySQL时间字符串)和 $avoid_die(可选布尔值,控制是否避免调用 wp_die())。
- 使用 wp_die() 时,可以传递额外参数如响应码、链接等来控制错误页面的行为。
- 函数依赖于 WordPress 数据库操作和用户权限检查,确保在适当的环境下调用。
原文内容
Checks whether comment flooding is occurring.
Description
Won’t run, if current user can manage options, so to not block administrators.
Parameters
$is_floodboolrequired-
Is a comment flooding occurring?
$ipstringrequired-
Comment author’s IP address.
$emailstringrequired-
Comment author’s email address.
$datestringrequired-
MySQL time string.
$avoid_diebooloptional-
When true, a disallowed comment will result in the function returning without executing wp_die() or die().
More Arguments from wp_die( … $args )
Arguments to control behavior. If
$argsis an integer, then it is treated as the response code.responseintThe HTTP response code. Default 200 for Ajax requests, 500 otherwise.link_urlstringA URL to include a link to. Only works in combination with $link_text.link_textstringA label for the link to include. Only works in combination with $link_url.back_linkboolWhether to include a link to go back. Default false.text_directionstringThe text direction. This is only useful internally, when WordPress is still loading and the site’s locale is not set up yet. Accepts'rtl'and'ltr'.
Default is the value of is_rtl() .charsetstringCharacter set of the HTML output. Default'utf-8'.codestringError code to use. Default is'wp_die', or the main error code if $message is a WP_Error.exitboolWhether to exit the process after completion. Default true.
Default:
false
Source
function wp_check_comment_flood( $is_flood, $ip, $email, $date, $avoid_die = false ) {
global $wpdb;
// Another callback has declared a flood. Trust it.
if ( true === $is_flood ) {
return $is_flood;
}
// Don't throttle admins or moderators.
if ( current_user_can( 'manage_options' ) || current_user_can( 'moderate_comments' ) ) {
return false;
}
$hour_ago = gmdate( 'Y-m-d H:i:s', time() - HOUR_IN_SECONDS );
if ( is_user_logged_in() ) {
$user = get_current_user_id();
$check_column = '`user_id`';
} else {
$user = $ip;
$check_column = '`comment_author_IP`';
}
$sql = $wpdb->prepare(
"SELECT `comment_date_gmt` FROM `$wpdb->comments` WHERE `comment_date_gmt` >= %s AND ( $check_column = %s OR `comment_author_email` = %s ) ORDER BY `comment_date_gmt` DESC LIMIT 1",
$hour_ago,
$user,
$email
);
$lasttime = $wpdb->get_var( $sql );
if ( $lasttime ) {
$time_lastcomment = mysql2date( 'U', $lasttime, false );
$time_newcomment = mysql2date( 'U', $date, false );
/**
* Filters the comment flood status.
*
* @since 2.1.0
*
* @param bool $bool Whether a comment flood is occurring. Default false.
* @param int $time_lastcomment Timestamp of when the last comment was posted.
* @param int $time_newcomment Timestamp of when the new comment was posted.
*/
$flood_die = apply_filters( 'comment_flood_filter', false, $time_lastcomment, $time_newcomment );
if ( $flood_die ) {
/**
* Fires before the comment flood message is triggered.
*
* @since 1.5.0
*
* @param int $time_lastcomment Timestamp of when the last comment was posted.
* @param int $time_newcomment Timestamp of when the new comment was posted.
*/
do_action( 'comment_flood_trigger', $time_lastcomment, $time_newcomment );
if ( $avoid_die ) {
return true;
} else {
/**
* Filters the comment flood error message.
*
* @since 5.2.0
*
* @param string $comment_flood_message Comment flood error message.
*/
$comment_flood_message = apply_filters( 'comment_flood_message', __( 'You are posting comments too quickly. Slow down.' ) );
if ( wp_doing_ajax() ) {
die( $comment_flood_message );
}
wp_die( $comment_flood_message, 429 );
}
}
}
return false;
}
Hooks
- apply_filters( ‘comment_flood_filter’, bool $bool, int $time_lastcomment, int $time_newcomment )
-
Filters the comment flood status.
- apply_filters( ‘comment_flood_message’, string $comment_flood_message )
-
Filters the comment flood error message.
- do_action( ‘comment_flood_trigger’, int $time_lastcomment, int $time_newcomment )
-
Fires before the comment flood message is triggered.
Changelog
| Version | Description |
|---|---|
| 4.7.0 | Introduced. |