📌 はじめに
私は現在、N.Designsという屋号で個人事業としてWeb制作を行っています。
今回公開したポートフォリオを兼ねた自作の公式サイト(https://n-designs.net)では、フルスクラッチで構築したお問い合わせフォームを実装しました。
その制作過程で、トークンベースのCSRF対策とセッション管理に大きく苦戦し、思った通りに動かないフォームに何度も頭を抱えました。
この記事では、そのときの経験を元に、技術的な実装の裏にある“リアルなつまずき”と、その改善に至るまでの気づきを共有したいと思います。
✅ 背景:セキュリティ強化のためトークン認証を導入
フォームに対する不正送信を防ぐため、CSRF対策として「ワンタイムトークン」方式を採用することにしました。
- PHP側でトークンを生成
- hiddenフィールドでフォームに埋め込む
- 送信時にPOSTパラメータで受け取り、セッションと照合
といった、よくある構成です。
ところが実装してみると、**「トークンが一致しない」「セッションが消える」「送信時に認識されない」**といった問題が次々と発生しました。
⚠️ セッションが保持されない?どこで消えてる?
当初はJavaScriptのPOST処理やトークンの値にばかり目を向けていたのですが、原因はもっと根本的な部分にありました。
🔍 見落としていた要因
session_start()の書き忘れや配置ミス- PHPファイルとHTMLのディレクトリ構造の違い
- Cookieのセキュリティ属性とパスの設定
- 別ファイルへの遷移時のヘッダー送信順序
- 非同期送信(fetch)時のヘッダー・CORSの挙動
フォームから送られてきたトークンと、セッション内に格納したトークンが照合できない=サーバーが保持していないという状態に陥っていたのです。
🛠 試行錯誤と改善の過程
▶️ ログ出力と送信トレースの徹底
トークンやセッションの中身を一時的にログとして出力し、どこで値が途切れているのかを追跡。
フォーム送信からリダイレクト、完了ページまでの全体の流れを視覚的に把握するよう努めました。
▶️ ファイル構成の見直しと統一
HTMLやVueのテンプレートとは別にPHPを配置していたため、セッションが想定通りに展開されない問題が発生。
- PHPファイルの格納階層とセッションパスの整合性
- POST対象とセッション発行元のURLのオリジン差異
こうした細かな構成差が目に見えない不具合を引き起こしていました。
▶️ JavaScript側との責任分離
- フロントは入力補助とUIの制御
- PHPはバリデーション・トークン管理・送信処理のみに限定
という役割分担を明確にしました。特にVueとの兼ね合いで、フォーム内容はHTMLのまま維持しつつ、VueはDOM制御だけにとどめるという方針に切り替えたことで、セッションと衝突するリスクを抑えることができました。
🔎 制作の学び:コード以前に「構成の理解」が重要だった
今回痛感したのは、「コードが正しい=動く」ではないということです。
HTML、CSS、JS、PHPが正しく書かれていても、
- サーバーの挙動(セッションの保存タイミング)
- ドメイン・ディレクトリの分け方
- HTTPヘッダーの扱い(Cookie、Referer)
など構造的な理解がなければ、思わぬトラブルを生むということでした。
💬 現在の構成と成果
今では、トークンの送受信・照合、バリデーション、エラー表示、完了ページ遷移までが安定して動作し、フォームを通じたお問い合わせ受付が問題なく稼働しています。
今後はGoogle reCAPTCHAの導入や、より詳細なログ管理なども視野に入れています。
📝 まとめ:この経験が“信頼できる制作者”への一歩に
今回のトラブルは、「本番用の自作フォームを一から構築してみよう」と思わなければ出会うことのなかったものです。
知識と実装が地続きで結びつくのは、実践だけ。この経験は、自分のWeb制作に対する考え方を大きく変えてくれました。
- ✅ 初心者でもセキュリティは後回しにしない
- ✅ つまずいたときは、構造から見直す
- ✅ なにより「ユーザーが安心して使えるフォーム」を優先する
これからWebサイトを作ろうとしている方、フォームを自作しようとしている方の参考になれば幸いです。



コメント