執筆中
C++によるCAPTCHA(画像認証)の実装です。
特徴は、
制限事項
万一プログラムが誤動作した際に、サーバ運営会社や他の利用ユーザに迷惑をかける恐れがあります。自分が管理権を持ったサーバーでのみ実行するなど、慎重に運用してください。このプログラムを使用したことによる結果について、作者は一切の責任を負いません。
上の書庫ファイルを展開して、captchaディレクトリに移動し、makeでコンパイルします。
実行に必要なファイルは次の通り。
ファイル名 | 属性 | 備考 |
---|---|---|
captcha.cgi | 755 | CGI本体 |
captcha.digits.cgi | 644 | フォント画像 |
captcha.status.cgi (空のファイル) | 666 | セッション情報 |
上記すべてのファイルをバイナリモード(コード変換を行わない)でサーバに転送します。
captcha.cgiをウェブブラウザから引数無しで実行すると、このページの上部に表示されているような「CAPTCHA」の文字が表示されます。もし、Internal Server Errorが表示される場合には、ファイルの属性と、転送モードを確認してください。特にバイナリモードで転送しないと絶対に動作しないので注意してください。
captcha.cgiをスクリプトから、generate引数を付けて実行すると、id(識別コード)が帰ります。第二引数の数値は桁数を指定します。
Rubyでの例を示します。
captcha_id = `./captcha.cgi generate 3`.chomp
idは20桁のランダムな英数字から成ります。
captcha.cgiをウェブブラウザからid引数を付けて実行すると、画像が表示されます。
Rubyでのフォームの実装例を示します。
<input type=hidden name=id value="#{captcha_id}">
<img src="captcha.cgi?id=#{captcha_id}"><br>
上に表示されている数字を入力して送信ボタンを押してください<br>
<input type=text name=captcha>
captcha.cgiをスクリプトからfindコマンドとidを付けて実行すると、数値文字列が帰ります。この文字列と、フォームから入力された文字列を比較して、一致したら認証をパスしたことになります。
error = ''
if cgi.has_key?('submit') && ENV['REQUEST_METHOD'].upcase == 'POST' captcha_id = cgi['id'] if captcha_id =~ /^[0-9A-Za-z]+$/ accept = false cap = `./captcha.cgi find #{captcha_id}`.chomp if cap != '' && cap == cgi['captcha'] accept = true else error += "画像認証が失敗しました。" end if accept # 更新処理を行う
captcha.cgiをverifyコマンドとid、および比較文字列を付けて実行すると、成否が帰ります。
./captcha.cgi verify ug2UfSffnLNuJhOqqhQF 1,3:945
上の例では、2文字目(ゼロオーダーで1文字目)から始まる3桁が 945 であるかどうか検証し、一致した場合は標準出力に pass をを出力し、異なった場合は fail を出力します。
スクリプトから、captcha.cgiを起動する際、文字列にセミコロン ( ; ) やパイプ ( | ) などが含まれると、OSコマンドインジェクション脆弱性による攻撃ができる恐れがあり、最悪、OS環境を破壊することができてしまいますので、慎重に実装する必要があります。
執筆中
WordPress 3.9.1 に組み込んでみました。プラグインではありません。phpファイルを直接書き換えています。
130行目付近
wp_die( __('ERROR: please type a comment.') ); $cap_id = trim($_POST['captcha_id']);
$captcha1 = trim($_POST['captcha1']);
$captcha2 = trim($_POST['captcha2']);
$captcha3 = trim($_POST['captcha3']);
if ( $captcha1 == ''
&& $captcha3 == ''
&& preg_match('/^[0-9]+$/', $captcha2)
&& preg_match('/^[0-9A-Za-z]+$/', $cap_id)
&& trim(exec(ABSPATH . 'captcha.cgi verify ' . $cap_id . ' 1,3:' . $captcha2)) == 'pass'
) {
// ok
} else {
wp_die( __('Error: CAPTCHA verification failed.') );
} $comment_parent = isset($_POST['comment_parent']) ? absint($_POST['comment_parent']) : 0;
2200行目付近
<?php echo $args['comment_notes_after']; ?> <?php $cap_id = exec(ABSPATH . 'captcha.cgi generate 5'); ?>
<style>
<!--
#captcha1 {
display: none;
}
#captcha3 {
display: none;
}
-->
</style>
<p>CAPTCHA(画像認証)</p>
<p><img src=<?php echo site_url('captcha.cgi' . '?id=' . $cap_id); ?>></p>
<p>上の画像の<b>最初と最後を除いた3桁の数字</b>を入力して、送信ボタンを押してください。<br>
</p>
<p class="comment-form-captcha"><input id="captcha1" name="captcha1" type="text" style="width:5em;" /></p>
<p class="comment-form-captcha"><input id="captcha2" name="captcha2" type="text" style="width:5em;" /></p>
<p class="comment-form-captcha"><input id="captcha3" name="captcha3" type="text" style="width:5em;" /></p>
<input name="captcha_id" type="hidden" value="<?php echo $cap_id ?>" /> <p class="form-submit">
この例では、3つのテキストフィールドを用意し、そのうち1番と3番をダミーとし、2番目のフィールドのみ検証します。ダミーフィールドに値が入っていた場合は、即座に検証失敗とします。
プラグイン化や多言語化を行って頂ける、PHPに詳しくて親切な方、もしいらっしゃったらご連絡ください。
執筆中