CodeIgniterのCSRF対策を完全解説!フォーム処理のセキュリティ手順
生徒
「CodeIgniterでフォームを作っているのですが、CSRF対策っていうのが必要だと聞きました。それって何ですか?」
先生
「CSRFは、悪い人が本人になりすまして勝手に投稿や買い物をさせてしまう攻撃のことです。CodeIgniterには、これを防ぐための強力な機能が備わっていますよ。」
生徒
「難しそうですね…。初心者でも設定できますか?」
先生
「大丈夫です。設定ファイルを数行書き換えるだけで、自動的にガードを固めることができます。具体的な手順を一緒に見ていきましょう!」
1. CSRF対策とは?初心者にもわかりやすく解説
プログラミングの世界でよく耳にするCSRF(シーサーフ)とは、「Cross-Site Request Forgery(クロスサイト・リクエスト・フォージェリ)」の略称です。 日本語では「サイト間リクエスト偽造」と呼ばれます。パソコンを触り始めたばかりの方には少し難しい言葉ですが、身近な例えで考えてみましょう。
例えば、あなたが銀行の窓口で手続きをしているとします。そこに、あなたの顔にそっくりな「お面」をかぶった偽者が現れて、「私の口座から100万円を別の場所へ送ってください」と窓口の人に嘘の命令を出すようなものです。 インターネット上でも同じように、あなたがログインしている状態を悪用して、知らない間に勝手な操作をされてしまう危険があるのです。
CSRF対策とは、この「偽者からの命令」を見破るための仕組みです。CodeIgniterという便利なPHPの道具(フレームワーク)を使えば、 「合言葉」のようなトークンを発行して、正しい利用者からの送信かどうかを自動でチェックできるようになります。
2. CodeIgniterでCSRF保護を有効にする設定手順
CodeIgniterでこの守りを固めるには、まず設定ファイルを確認する必要があります。プログラムの細かい動きを決める「ルールブック」を書き換えるイメージですね。
まずは、プロジェクトの中にある app/Config/Filters.php というファイルを探してみましょう。
このファイルの中には、Webサイト全体にかける「フィルター(網目)」の設定が書かれています。ここで「csrf」という機能を有効にすることで、 サイトに送られてくるすべてのデータに対して、厳しいセキュリティチェックが行われるようになります。
// app/Config/Filters.php の設定例
public $globals = [
'before' => [
'csrf', // ここに csrf を追加するだけで、全てのフォーム送信がチェックされます!
// 'honeypot',
],
'after' => [
'toolbar',
// 'honeypot',
],
];
このように設定するだけで、CodeIgniterは自動的に「合言葉」を持っていない送信をエラーとして弾いてくれるようになります。 セキュリティの基本は「怪しいものは通さない」ことですから、この設定はWeb開発において非常に大切な第一歩となります。
3. フォームにセキュリティトークンを埋め込む方法
設定を有効にしたら、次は実際の入力画面(フォーム)に「合言葉」を埋め込む作業が必要です。 専門用語でこの合言葉をCSRFトークンと呼びます。 CodeIgniterには、このトークンを自動で作成して隠してくれる便利な命令が用意されています。
手動でHTMLを書くこともできますが、CodeIgniterの「フォームヘルパー」という機能を使うのが一番簡単で確実です。
以下のコードのように csrf_field() という命令を一行足すだけで、画面上には見えない「秘密の合言葉」がフォームの中に隠されます。
<form action="/submit" method="post">
<?= csrf_field() ?> <label for="username">お名前:</label>
<input type="text" name="username" id="username">
<button type="submit">送信する</button>
</form>
この csrf_field() が実行されると、実際のWebブラウザ上では以下のような隠し項目(input type="hidden")に変換されて出力されます。
<input type="hidden" name="csrf_test_name" value="d1a2b3c4e5f6g7h8i9j0..." />
このランダムな長い文字列が、その時だけ有効な「一度きりの合言葉」になります。これがあるおかげで、外部からの不正な攻撃を防ぐことができるのです。
4. セキュリティ設定のカスタマイズとSecurity.php
CSRF対策のより細かいルールを設定したい場合は、 app/Config/Security.php というファイルを編集します。
ここでは、合言葉の有効期限や、合言葉を入れる箱の名前(トークン名)などを自由に変更することができます。
例えば、「一度フォームを送ったら、合言葉を新しいものに取り替える」という設定(Regenerate)や、「Cookie(クッキー)」というパソコン内の保存場所にどのような名前で保存するかを決めることができます。 初心者のうちは初期設定のままでも十分安全ですが、大規模なサイトを作る際にはこれらの設定を調整することもあります。
// app/Config/Security.php の主な項目
public $csrfProtection = 'cookie'; // クッキーを使って保護する
public $tokenName = 'csrf_test_name'; // 合言葉のラベル名
public $headerName = 'X-CSRF-TOKEN'; // 通信ヘッダーでの名前
public $cookieName = 'csrf_cookie_name'; // クッキーの名前
public $expires = 7200; // 合言葉の有効期限(秒)
public $regenerate = true; // 送信するたびに合言葉を新しくする
$regenerate = true; にしておくと、セキュリティ強度は上がりますが、ブラウザの「戻る」ボタンを押したときにエラーが出やすくなるという特徴もあります。
自分のサイトの使い勝手に合わせて調整してみましょう。
5. AJAX(非同期通信)でCSRF対策を行うテクニック
最近のWebサイトでは、ページを切り替えずにデータをやり取りする「AJAX(エージャックス)」という技術がよく使われます。 この場合も、通常のフォームと同じようにCSRF対策が必要です。 JavaScriptを使ってデータを送る際には、合言葉をデータの「中身」に入れるか、「通信のヘッダー」という目立たない場所に含める必要があります。
初心者の方には少しレベルが高いかもしれませんが、 「JavaScriptでデータを送る時も、必ず合言葉をセットで送らなければならない」というルールだけ覚えておけば大丈夫です。 CodeIgniterではヘッダー情報を読み取る機能も充実しているので、スムーズに連携が可能です。
// コントローラー側でトークンの値を取得してJavaScriptに渡す例
$data = [
'token_name' => csrf_token(), // 合言葉の名前を取得
'token_hash' => csrf_hash(), // 合言葉の正体(ハッシュ値)を取得
];
echo json_encode($data);
このように、プログラム側から現在の合言葉を教えてあげることで、JavaScriptなどの別の道具を使っている時も一貫したセキュリティを保つことができるようになります。
6. もしエラーが出た時は?CSRFエラーの対処法
CSRF対策を設定すると、たまに「403 Forbidden」というエラー画面が表示されることがあります。これは「アクセスが禁止されています」という意味です。 ほとんどの場合、原因は「合言葉が送られていない」か「合言葉が古くなって間違っている」かのどちらかです。
まずは、以下のチェックリストを確認してみましょう。
- フォームの中に
csrf_field()を書き忘れていないか? - 複数のタブを開いて操作したせいで、合言葉が更新されてしまっていないか?
- 設定ファイルのドメイン設定(App.phpのbaseURL)が正しく記述されているか?
プログラムは非常に正直です。ルールが少しでも守られていないと、あなたのサイトを守るためにあえて「エラー」を出して止めてくれます。 エラーが出た時は、守りがしっかり働いている証拠だと思って、落ち着いてコードを見直してみてください。
7. セキュリティを意識したプログラミングの第一歩
パソコンを触ったことがない方にとって、プログラミングは魔法のように見えるかもしれません。しかし、その魔法を安全に使うためには、今回学んだCSRF対策のような「鍵」をかける習慣がとても大切です。 CodeIgniterを使うことで、本来なら非常に複雑な計算が必要なセキュリティ対策も、たった数行のコードで実現できることがわかったと思います。
最初は仕組みを完璧に理解できなくても構いません。「外から勝手に操作されないように、見えない合言葉をやり取りしているんだな」というイメージを持つだけで、あなたのエンジニアとしてのレベルは格段にアップします。 これからも、安全で楽しいWebサイト作りを目指していきましょう!