1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

【PHP】CSRF 対策【かんたん】

Last updated at Posted at 2022-07-15

はじめに

Laravelなどを使わず、シンプルなPHPでフォームを作る場合、csrf対策を自力で行う必要があります。

まあそんな機会は多くないかもしれませんが、覚えておいて損はない、、!
ということでやっていきましょう。

入力画面、確認画面、結果画面、3画面の一般的なフォームで実装していきます。

入力画面

ランダムな文字列で生成したトークンを、セッションに格納します。
すでにセッションに存在する場合は、そちらを使います。

entry.php
<?php
session_start();  //セッション開始

  $token = '';
  if ( isset( $_SESSION[ 'token' ] ) || !empty( $_SESSION[ 'token' ] ) ) {
    $token = $_SESSION['token']; //セッションにすでにあるとき
  } else {
    $token = bin2hex(random_bytes(32)); //トークンを生成
    $_SESSION['token'] = $token;   //セッションにトークンを格納
  }

type=“hidden”で隠したinputに、トークンを置き、他の入力内容とともにsubmitします。

entry.php
<form action="./confirm.php" method="POST">
   <input type="hidden" name="token" value="<?php echo $token; ?>"> //隠しフィールドにトークンを設置し、フォーム送信時に一緒に送る
   <input type="submit" value="確認">
</form>

確認画面

POSTで送られてきたトークンがセッションにあるトークンと一致するかをチェックしています。
一致しない場合は、入力画面に戻す。
一致する場合は、またinputに設置して送信します。

confirm.php
<?php
session_start();  //セッション開始

//トークンチェック
if (isset($_POST['token']) && isset($_SESSION['token'])) {
    $token = $_POST['token'];
    if ($token != $_SESSION['token']) { //トークンが一致しない場合は処理を中止
        header("Location: entry.php");
        echo ('アクセスが中断されました。');
        exit();
        }
    } else {  //トークンが存在しない場合は処理を中止する
        header("Location: entry.php");
        echo ('不正なアクセスです');
        exit();
    }
confirm.php
<form action='./complete.php' method='POST'>
        <input type='hidden' name='token' value='<?php $token; ?>'>  
        <input type="submit" value="送信する">
</form>

結果画面

結果画面でも、確認画面と同じようにチェックすればOKです。

complete.php
<?php
session_start();  //セッション開始

//トークンチェック
if (isset($_POST['token']) && isset($_SESSION['token'])) {
  $token = $_POST['token'];
  if ($token != $_SESSION['token']) { //トークンが一致しない場合は処理を中止
      header("Location: entry.php");
      echo ('アクセスが中断されました。');
      exit();
      }
  } else {  //トークンが存在しない場合は処理を中止する
      header("Location: entry.php");
      echo ('不正なアクセスです');
      exit();
  }

最後に処理が完了したら、

session_destroy();

で、セッションを破棄することをお忘れなきよう!

以上、これにて完成となります。

おわりに

いかがだったでしょうか。
Laravelだと、@csrfと書くだけですが、Laravelが使えない場合でも、意外と簡単に作ることができます。

ぜひ参考にしてみてください!

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?