アメリカでがんばりましょう: MT Comment Spam と闘うポイントはSpamを投稿するのは人ではなくて、専用のプログラムだということ。
hidden 属性のフィールドを追加して、コメントの投稿時にそのフィールドがあれば、人からの投稿。無ければプログラムからのSpam投稿ということで、拒否すればいいというわけだ。
およそ1年ほど前に書いた上のエントリ。 この設定のおかげで、コメントスパムの投稿は結構押さえられていたが、最近になってその数が再び増えてきた。 理由はdistance: Comment SPAM WAR !! にもあるように、個別エントリ(Permalink)を読みこんだあと、コメント投稿用のフォームを解析し、投稿するというコメントスパムプログラムが開発されたことだった。
この新手のコメントスパムプログラムには、前回書いたように隠しフィールドを埋めこむ方法では防げない。 そこで、今度は次のような仮説をもとに対策を考えてみた。
「JavaScript をオンにした環境で、Submit ボタンを押したとき(onSubmit イベント時)に、隠しフィールドの値を設定すれば、人がボタンを押したときは正しい値が、コメントスパムプログラムが HTML だけ解釈して投稿したときは間違った値が送られる」
JavaScript が標準でない、携帯電話のブラウザなどからコメントを受けつけているサイトではコメントを投稿できなくなるが、パソコンのブラウザだけを対象にしているサイトの場合はこの方法で多くのコメントスパムプログラムが回避できると思う。
MovableType の Version 2.X 系の場合、具体的には以下のように設定する。
前提: 以前の MT Comment Spam と闘う に書いてある修正が終わって、隠しフィールド snoop = goaway がある場合に有効なコメント投稿だとする。
1. 個別エントリ (Individual Entry Archive) のテンプレートの、コメント関係の JavaScript が定義されている部分 (function forgetMe() の次あたり) に以下の JavaScript 関数を追加する。 keyword のところには "goaway" を反対から書いた文字列をセットすることで、簡易的に JavaScript を解析した場合も防ぐことができる。 snoop の部分を自分が設定した隠しフィールドの名前に変えるのを忘れないで。
function avoidSpam() {
keyword = "yawaog";
document.comments_form.snoop.value = "";
for (i=keyword.length-1; i>=0; i--)
{
document.comments_form.snoop.value += keyword.charAt(i);
}
}
2. 設定した隠しフィールドの値(value)を適当に書きかえる。<input type="hidden" name="snoop" value="fakekey"/>
3. コメントのフォーム定義(<form>)の中にある onsubmit の部分を書きかえる変更前:
onsubmit="if (this.bakecookie[0].checked) rememberMe(this)">変更後:
onsubmit="avoidSpam(); if (this.bakecookie[0].checked) rememberMe(this)">
以上。 HTML を解釈してフォームの構造をとりだすのは比較的簡単だが、これに JavaScript の解釈までしながらコメントスパムをばらまいていくようにするのは手間と時間がかかると思う。このサイトでも1週間ほど試してみたが、今のところ問題は出ていない。 みなさんもよかったらどうぞ。
---
(10/26 追記)
オリジナルのエントリ MT Comment Spam と闘う では mt-comments.cgi の変更は、隠しフィールドのデータの有無しかしていなかった。
これでは、いくら JavaScript で文字を置き変えても意味がないので snoop=goaway の隠しフィールドの場合は以下の太字の部分に変更する必要がある。
use CGI qw(:standard);
if ($ENV{'REQUEST_METHOD'} eq "POST") {
my $data = param('snoop');
die if ($data ne 'goaway');
}
指摘してくれた妻、エライ。

はらしょー! さっそく組み込んでみます。