WP Fastest CacheとSiteGuard WP Pluginでひらがな画像認証に問題発生

キャッシュ系プラグインと画像認証コンピュータ関連
スポンサーリンク

先日サーバーを引っ越して使い始めたキャッシュ系のプラグイン。
WP Fastest Cache

さらにセキュリティを少しでも考えたら入れておこう、のセキュリティ系プラグイン。
SiteGuard WP Plugin

この二つを同時に使用していたところ、とある問題に打ち当たってしまった。

コメントの画像認証(Really Simple CAPTCHA)が機能していない!

なんか「CAPTCHA」って文字だけで、画像が表示されていないことに先日気がついた。

色々と情報を探してみて、同じ問題に直面した人が他にもいる事を知る。
でもどちらかのプラグインを停止させる、というのがほとんどのようです。

仕方がないので「SiteGuard WP Plugin」のコメント欄における画像認証だけ切ってみた。

しかし僅か2日で多量のスパムコメント。
簡易の「ひらがな認証」があるだけでも、スパムコメントに対しては絶大な効果があるらしい。

かといってキャッシュ系を切れば安かろう遅かろうのサーバーでは、相当きつくなってしまう気がする。

でもなんとかできないの?
そう思って対処法を考えてみました。

スポンサーリンク

問題の原因

考えてみれば当たり前だけれども、
ページキャッシュを行うキャッシュ系プラグインはその名の通り、動的に生成されるページを静的HTMLとしてキャッシュし、次回からそれを表示させることで速度向上を図ります。
(キャッシュ系と一言で言っても幾つか仕組みがあるようですが)

一方「SiteGuard WP Plugin」に使われている「Really Simple CAPTCHA」はWordPressの仕組みにプラグインとして組み込まれ、コメント欄の表示やログイン画面の表示など動的にページを生成する際に動作しています。

故にキャッシュされた静的HTMLを返してくるだけでは動かず、画像認証の部分は古いまま。
結果として画像のリンクも切れてしまい、alt属性で記述されている「CAPTCHA」が表示されることになるわけです。

当然、何を入力しようが通らない。

WP Fastest Cacheの除外パスで設定しても意味はない?

上述の通り WP Fastest Cache ではあらかじめ1枚のページ(ファイル)としてキャッシュを作り、それを閲覧者に返すことで毎回生成する手間を省いているわけです。当然「CAPTCHA」部分のソースコードもキャッシュを作った時のものから変わることはありません。
なのでいくら除外パスで設定しようともHTMLファイル内のソースコード(ファイルパス)が変わらなければリンク切れは起こってしまうのです。

問題の切り分けと対処法

とりあえず今回なんとかしたいのは、
このコメント投稿時の「ひらがな画像認証」を復活させる事。

現段階で問題になっているのは、
「動的に生成しない(きっかけがない)から、画像認証に必要な前処理が行われない」
ということ。

つまり対処としてはキャッシュ画面(静的HTML)であっても、
認証用のファイルが新たに用意され、その部分の表示さえ更新されればそれで良い
のではないか。

細かい仕様などの説明は割愛、本家や他サイトに譲るとして、
具体的には

  1. 認証用の画像とハッシュ値が書かれたファイルの生成
  2. 生成された情報を受け取って画像とキー(数字)部分を書き換える

これができれば良いわけだ。

対処用スクリプトの作成

キャッシュされたHTMLを表示する際、該当部分を書き換えるのにはjQueryを使えば良い。
問題は認証画像の生成あたり。

もともとのプラグインはいじりたくなかったので、
別途Javascriptとphpのファイルを用意し、Really Simple CAPTCHAのクラスファイルを読み込む事で対応することにした。

流れとしては、

  1. キャッシュファイルかどうかの判別
    (キャッシュファイルには一番最後にコメントアウトされた文言がある)
  2. キャッシュファイルであったら、$.ajaxでphpファイルにアクセス
  3. phpファイルでは画像生成などの一連の処理を行わせ、キーとなる数値(生成されるファイル名)を返す。
  4. 受け取った数値をもとにjQueryで画像のurlなどを更新

こんな感じ。

ファイルの置き場所はプラグインフォルダ直下に。

キャッシュの判別、情報の書き換え

こちらはJavascriptで対応。

「getcaptchaimg.js」

function getPrefixNum(){
	var myurl = "//www.自分のドメイン.com/wp/wp-content/plugins/"; //プラグインフォルダへのパス
	jQuery.ajax({
		type: "GET",
		cache: false,
		url: myurl+"getcaptchanum.php",
		datatype: 'text'
	}).done(function(n){
		jQuery("img[alt='CAPTCHA']").attr('src', myurl+'siteguard/really-simple-captcha/tmp/'+n+'.png'); //(※1)
		jQuery("#siteguard_captcha_prefix").attr('value', n);
	});
}

jQuery(function(){
	var nd = (jQuery("img[alt='CAPTCHA']").length) ? document.lastChild : "";
	if(nd.nodeType === document.COMMENT_NODE && ~nd.data.indexOf('WP Fastest Cache file was created')){ //(※2)
		console.log("This is a cached page, so let's kick that ass to work ! (CAPTCHA)");
		getPrefixNum();
	}
});

※2行目の「myurl = “//www.自分のドメイン.com/wp/wp-content/plugins/”;」を使用するドメインに置き換えてください。
例:

myurl = "//www.wholenotism.com/wp/wp-content/plugins/";

※1.画像の種類としてはpngを指定しています。
※2.現在(2017/05/13 ver0.8.6.8)の段階で確認できるコメント文字列を使っています。将来的に変わる可能性はあり。

【追記 2017/06/26】
コメント欄がないページでも認証用画像を作りに行っていたので修正しました。

【追記 2018/02/02】
https化に伴い、urlから「http:」を削除。

【追記 2019/07/11】
なんかおんなじ文字列が表示されるなぁと思ったらキャッシュを無効にしていなかった。
cache: falseを追記。
(ブラウザに残されたキャッシュは「サイトデータ」などの名称で保存されています。一度削除/クリアするか、期限が切れて新しく読み込まれないと反映されません)

認証画像およびハッシュ値テキスト生成

「getcaptchanum.php」

<?php
require_once( '../../wp-load.php' );
require_once( './siteguard/really-simple-captcha/siteguard-really-simple-captcha.php' );

$my_captcha_instance = new SiteGuardReallySimpleCaptcha();
$word = $my_captcha_instance->generate_random_word();
$prefix = mt_rand();
$my_captcha_instance->generate_image( $prefix, $word );

echo $prefix;
?>

このままでは直接アクセスされると普通に数値が返されてしまいます。

スポンサーリンク

その数字自体はimgタグにも書かれるファイル名であり、公開されている情報なので問題はないかと思いますが、アクセスする度に認証画像が作成されるため、頻度によってはサーバーに負荷がかかってしまう可能性があります。

・・・まぁもとからそういう仕様なんですが。

JavascriptをWordpressに登録

これは環境によって変わると思うので一例として。

現在このブログでは「Simplicity2」というテーマを使用させて頂いております。
その子テーマにある「footer-insert.php」に1行追加。

<script src="<?php echo WP_PLUGIN_URL; ?>/getcaptchaimg.js"></script>

他のテーマなどではwp_enqueue_script関数をfunctions.phpに記述すれば良いかと。
(「wp_enqueue_script」でググると有益なサイトが沢山見つかります。)

まとめ

まとめると、

  1. getcaptchaimg.js、getcaptchanum.phpの二つをプラグインフォルダ直下に配置
  2. jsファイルを読み込むようWordpressに登録

これでとりあえずキャッシュであっても画像認証が使えるようになります。
スパム対策として「Akismet Anti-Spam」も使っているのですが、できれば投稿される前にも対応しておきたかった。

ちなみにこの「Really Simple CAPTCHA」はシンプルかつ簡易的なものだと説明されています。

注: このプラグインは、名前の通り “really simple ( 本当にシンプル )” なもので、それほど強力な安全性はありません。堅牢な安全性が必要な際には、他のソリューションをお試しください。

(wordpress.org プラグイン Really Simple CAPTCHA より引用)

また、こちらのページではある問題が指摘されています。
Qiita 「SiteGuard WP Pluginの留意点」

とは言え、海外からのスパムを防ぐには十分すぎるものがあると思います。

尚、実験的かつ個人的に試してみた結果なので、この記事の内容を利用し損害が発生したとしても何ら責任は負いませんのであしからず。
あくまでも参考として、より良い解決法を探ってみてください。

ということで今回は以上!

コメント

  1. ひいろん より:

    はじめまして。
    当ブログでも同じくWP Fastest CacheとSiteGuard WP Pluginを併用していて同じ現象になりまして
    参考に(というかそのまま利用)させていただきました。
    技術的な事はちんぷんかんぷんな自分にとっては非常に有益な情報で助かりました(^^

    • watarywatary より:

      こんにちは。はじめまして。
      自分は横からちょっといじらせてもらっただけなので、
      素晴らしい仕事をしてくれたこれらプラグインの作者さんに感謝ですね。
      ともあれ、お役にたてたようで良かったです。(^^
      コメントありがとうございました。

タイトルとURLをコピーしました