- ベストアンサー
トークンとCSRF対策
- トークンを生成してセッションに格納し、CSRFのトークンをチェックする方法について説明します。
- トークンはget_csrf_token()関数で生成され、セッションに格納されます。
- is_valid_csrf_token()関数を使用して、送信されたトークンとセッションに格納されたトークンを比較します。
- みんなの回答 (2)
- 専門家の回答
質問者が選んだベストアンサー
>練習のためにMVCモデルで作成しています。formタグの箇所にCSRF対策を実装するつもりです。 なるほど。それでは各コントローラにHTTPのリクエストメソッドを確認する記述を書く必要があるので、以下のようなユーザ関数を作っておくと少し便利かもしれないですね。 /** * HTTPのリクエストメソッドが引数と同様であるか真偽値を返す * ex) if (is_method('post')) {} * * @param string $http_request_method GET|POST|PUT|DELETE|PATCH * @return bool */ function is_method($http_request_method) { return strtolower($_SERVER['REQUEST_METHOD']) === strtolower($http_request_method); } また、サンプルで書かせていただいたスクリプトは単独でCSRFトークンのチェックするようIF文で振り分けてますが、FORMのその他の入力値と同じタイミングで一緒に検証してもよいかもしれないです。 練習で使っているライブラリ(フレームワーク)でバリデーションをどのようにする設計なのかによりますが。 頑張ってください。
その他の回答 (1)
- hogehoge78
- ベストアンサー率80% (433/539)
一応、最小構成でかつ、べた書きである程度分かりやすいように、また、PHP5以上で動くように記載すると下記のような感じで動くと思います。 <?php if ($_SERVER['REQUEST_METHOD'] === 'POST') { // POSTされた場合 if (isset($_POST['csrf'])) { // POST値に、CSRFトークンが渡されてきているはず。 $token = $_POST['csrf']; } else { // POST値に、CSRFトークンが渡されてきていない場合 // とりあえず空文字設定しておく $token = ''; } if (is_valid_csrf_token($token) { // POST値のCSRFトークンがSESSIONのものと同様だった場合 // ここら辺にバリデーション処理とか登録処理とか書く } else { // CSRFトークンが不整合な場合 // エラーメッセージやエラー遷移や例外処理なんかをここに書く } } else { // POSTではない場合(GETとかその他) } // 質問者さんのスクリプトがどのようにHTMLを表示するかはわかりませんが、下に適当に入れておきますね。 // HTMLに渡すための変数を用意し、新しくCSRFトークンを生成する $csrf_token = get_csrf_token(); ?><html> <body> <form action="" method="POST"> <!-- FORMタグの中にhiddenのINPUTタグを用意し、CSRFトークン文字列を隠し属性で設定する --> <input type="hidden" name="csrf" value="<?php echo $csrf_token ?>" /> <!-- 以下普通に登録するためのINPUTやらTEXTAREAやらSELECTなんかを書く --> </form> </body> </html> ここまで、一連の質問投稿から推察するに、誰かの作ったアプリを読み解いて勉強しているのかなと思います。 自分自身で書いていないユーザ関数群をマニュアルなしに読み解いていくのは結構難しいと思いますので、もし理解が追い付かない場合は、簡単なフォームアプリから見直してみてもよいと思います。 セッションを使わない、セキュリティを気にしない文字列投稿だけを実装して、そのあとに徐々に機能を増やしていく、みたいな。
補足
回答ありがとうございます。練習のためにMVCモデルで作成しています。formタグの箇所にCSRF対策を実装するつもりです。