tips

WordPress のサイト内検索 SPAM への対策

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

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

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

対策の骨子は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 チェック Akismet使ってない人は不要
	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 ) をセットしてください。

「My upload images : メディアアップローダー付きのカスタムフィールドを設置するプラグイン。」への6件の返信

  1. 初めまして。

    add images をメディアライブラリを通さずに、ローカルから直接「ファイルを選択」でアップすることは可能でしょうか。
    その一点のみが懸念点でして、それが可能であれば是非使用させていただきたいのですが…
    ご確認いただけますと幸いです。
    よろしくお願いいたします。

    1. このプラグインは、通常の「メディアを追加」ボタンと同じ動作をします。

      「ファイルをアップロード」タブを選択すると、「アップロードするファイルをドロップ」または「ファイルを選択」から画像をアップロードすることができます。

  2. はじめまして。

    使わせてもらっています。
    まさに求めていたものそのままの機能で感激いたしました。
    jqueryのスライダーと合わせて使わせていただいてます。

    一つだけ教えてほしいのですが、
    記事の「設置&出力方法」のサンプルコードに追加で
    画像のキャプションを取得する方法はないでしょうか?
    お時間がありましたら教えていただけると助かります。
    よろしくお願いします。

    1. まだプラグインではなかったときの記事の名残があちこちにあって、出力例も含めていろんな箇所が怪しさ満載でしたので、目に付いた箇所だけ直しておきました。

      出力例の箇所に「タイトル・キャプション・代替テキスト・説明」のすべての出力ができるようなサンプルコードを書いておきました。適当にカスタマイズしてください。

    2. お早いお返事ありがとうございます。

      無事キャプションを呼び出すことができました!
      とても便利なプラグインなのでこれからも応援しております。

  3. はじめまして。

    まさに欲しかった機能にぴったりのプラグインで大変助かっています。

    そこで1つ気になるところがありました。
    wordpressをdebugで実行していると、Noticeが多数出力されているようです。
    動作には特に問題はないですが、気になりましたのでコメントさせていただきました。

    1. ご報告ありがとうございます。

      返信が遅くなりました。
      他のプラグインもerror_reportingでチェックしただけでWP_DEBUGをしてません。裏側で出ているnoticeはそのうちそのうちと、思いつつ無視してました^^;

      とりあえずmy upload imagesだけやって1.3.5にアップデートしました。
      おいおい、他のも・・・?

  4. お世話になります

    参考になりました

    一つ質問ですが、
    あと、テーマ内で使用するには、ループ中でカスタムフィールドの配列を呼び出して下さい。
    とありますが、これはどこで呼び出せばいいですか?
    function.phpの中でしょうか、テンプレートのphpファイルでしょうか??

    1. >function.phpの中でしょうか、テンプレートのphpファイルでしょうか?


      テンプレートのphpファイルの中です。singleやctegoryなどのループの中でカスタムフィールド値を呼び出すときと同じように設置してみてください。

    2. お世話になります

      ありがとうございます
      マイアップロード画像を管理画面に表示できました。

      しかし選んだ画像をテンプレートファイルに書き込むのが出来てません・・・

      画像をアップロードして、
      画像を選択すると、アイテム画像の追加削除の下に、
      選択した画像が出ます。

      しかし、公開(または更新)ボタンを押すと、
      表示されていた画像が消えてしまうのですが、
      これはデータベースへの書き込みが上手く行っていないのでしょうか?

      重ね重ね質問で申し訳ございません。。

      ご教示いただけたら幸いです。。

    3. >これはデータベースへの書き込みが上手く行っていないのでしょうか?

      試しにここで提示している関数群を丸ごとコピペして確認してみましたが、こちらでは問題なく動作しています。
      初歩的なことを伺いますが、きっちりとコピーできているか確認して下さい。また、phpのタグ 

      <?php

       と 

      ?>

       がfunctions.php内に元々あったタグと重複したりしていませんか?

    4. ありがとうございます。

      metabox.phpというファイルにまるごとコピペして
      function.phpでrequire(‘metabox.php’);という形で、
      読み込んでますので、そういうミスはないかと・・・

      書き換えたのは、私の場合投稿ではなく、カスタム投稿タイプで使いたいので、
      add_meta_boxの引数を
      add_meta_box( ‘my_upload’, ‘マイアップロード画像’, ‘my_upload_postmeta’, ‘work’, ‘normal’,’high’ ); // ポジションはsideが推奨

      とpostからカスタム投稿タイプのworkに書き換えただけです。。。

      他にカスタムフィールドを使っていますので、
      それの書き込み関数とバッティングしているとかありますでしょうか??

      XAMPP1.8.3 PHP5.5.6で動かしています。。。

    5. 何パターンかのカスタム投稿タイプで確認済みです。

      はるのぶさんの指定方法でカスタム投稿タイプ「work」に対してそのまま使えるかと思います。

      画像が書き込まれないという症状からすると、カスタム投稿タイプのサポート設定の’capability_type’がデフォルトではないか’post’か’page’以外のものに指定されているためにパーミッションチェックを通らない、という可能性が考えられます。

      capability_typeの設定が別のものになっていて、かつこだわりがなければ’post’に設定してみて下さい。
      capability_typeが変更できない理由がある場合、save_my_upload_postmeta関数内の分岐箇所 ( ‘page’ == $_POST[‘post_type’] )以下を次のように書き換えてみてください。(未検証です)

      if ( 'page' == $_POST['post_type'] ) {
          if ( !current_user_can( 'edit_page', $post_id ) ) // パーミッションチェック
          return $post_id;
      } elseif ( 'work' == $_POST['post_type'] ) {
          if ( !current_user_can( 'edit_work', $post_id ) ) // パーミッションチェック
          return $post_id;
      } else {
          if ( !current_user_can( 'edit_post', $post_id ) ) // パーミッションチェック
          return $post_id;
      }

      試しに上記パーミッションチェックの箇所をすべて削除してみてもらえば、そこが原因かどうか分かると思います。

    6. ありがとうございます。

      capability_typeは設定されていませんでしたので、
      ‘post’にしてみましたが、現象変わらず、
      また、パーミッション設定をはずしたり、
      教えていただいたコードに変えましたが、
      現象変わらずです。。。

      あとはどこも変えてないです。

      他にもカスタム投稿タイプの中で、
      カスタムフィールドは使っていますが、
      それは保存されています。。。

      初心者なので、どこをどう調べてよいか分からず、困っています。。。

      申し訳ございませんが、
      よろしくお願いします。。。

    7. いただいたfunctions.phpを見ました。

      58行目の echo $my_upload_li を echo isset($my_upload_li) に改変されているのが原因です。

      この機に、変数の定義ミス警告が出ないようにコードもアップデートしておきますので、そちらをお使いください。

  5. 反映ありがとうございます。

    p.media.controller.Libraryで指定した設定ですと、メディアライブラリを一度選択すと画像を選択するのボタンが変になるのはこちらの検証環境のみでしょうか?

    1. エラーのご報告ありがとうございます。

      今までまったく気がついてませんでした。
      左のツールバーはプロパティの設定を反映させるために表示されていただけで、本来不要なのでjQueryで無理矢理取り除くことにしました。ボタンのテキストが消える原因は調べてないのですが、これで画面遷移がなくなるので、結果オーライで^^;

      なお、同様のアップローダーを使っていたウェルカート用プラグインはそもそも添付画像しか見えなくていいので、もっとシンプルな仕様に変更しておきました。

コメントを残す

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