tips

WordPress のサイト内検索 SPAM 対策について

WordPress のサイト内検索を利用した SPAM

WordPress のサイト内検索を利用した悪質な SPAM 行為ですが、SEO 的にもマイナスになる可能性があるので対策は必須です。

これまではテーマ側で noindex して済ませていました。Googleの SEO としてはそれで OK なのですが、私の周囲で俄に増加傾向にあって、踏み台にされるんじゃないかという怖れもあり、抜本的な対策を講じることとしました。そもそも、検索SPAM対策はコアに組み込むべきだと思うんですが。

対策の骨子は2つあります。

  • 検索文字数の制限
  • Akismet を利用した SPAM 判定

まず文字数は、大半のSPAMが長い文字列を使ってきていることから、有効性が高いと言えます。私の設置した感じではこれで7割くらいの SPAM がひっかかっていました。
次に Akismet の SPAM チェックを援用します。もちろん Akismet のインストール&有効化が必要です。
これらの制限に引っかかったクエリの表示には 500 ステータスを返そうというわけです。効率を重視するスパマーなら(そんなものがいればですが)これで寄ってこなくなるかも知れません。

コード

functions.php に丸写しで動くはず。

add_action( 'parse_query', function ( $query ) {
	if ( defined( 'REST_REQUEST' ) && REST_REQUEST || defined( 'DOING_AJAX' ) && DOING_AJAX || is_admin() || !$query->is_main_query() || !$query->is_search ) return;
	$search_query = $query->get( 's' );
	if ( !$search_query ) return;

	// 文字数制限
	if ( strlen( $search_query ) > 80 && mb_strlen( $search_query ) > 40 ) { // 半角80文字 & マルチバイト約40文字
		status_header( 500 );
		exit;
		// $query->set_404();
		// status_header( 404 );
	}

	// Akismet による SPAM チェック
	if ( class_exists( 'Akismet' ) && Akismet::get_api_key() ) {
		$user_ip = isset( $_SERVER['HTTP_X_REAL_IP'] ) ? $_SERVER['HTTP_X_REAL_IP'] : ( isset( $_SERVER['HTTP_X_FORWARDED_FOR'] ) ? trim( current( preg_split( '/,/', $_SERVER['HTTP_X_FORWARDED_FOR'] ) ) ) : $_SERVER['REMOTE_ADDR'] );
		$akismet_fields = http_build_query( array(
			'blog' => esc_url( home_url() ),
			'blog_lang' => get_locale(),
			'comment_type' => 'search_query',
			'comment_content' => sanitize_text_field( $search_query ),
			'contact_form_subject' => sanitize_text_field( $search_query ),
			'comment_author_IP' => $user_ip,
			'user_ip' => $user_ip,
			'referrer' => sanitize_text_field( $_SERVER['HTTP_REFERER'] ?? '' )
		) );
		$response = Akismet::http_post( $akismet_fields, 'comment-check' );
		if ( 'true' == $response[1] ) {
			status_header( 500 );
			exit;
			// $query->set_404();
			// status_header( 404 );
		}
	}
});


文字数制限のところは、任意に変更してください。サイトの性質によっては、もっと長い方がいいかもですし、逆に余計なリソースは使いたくなければ、もっと少し厳しめでいいでしょう。

返却するヘッダステータスはサーバーやサイトのリソースの削減のため 500 にしていますが、検索することに比重を置いたデータベースサイトなどの場合は、404 にしてテンプレートで表示をコントロールする方がユーザーに優しく設計できるでしょう。その場合は、status_header(500) と exit を削除して$query->set_404() と status_header( 404 ) をセットしてください。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です