前提
PHPでワンタイムトークンの実装
実現したいこと
・login.phpで$_SESSION['csrfToken']と$_POST['csrfToken']が一致しないので、一致させたい
・login.phpで取得した$_SESSION['csrfToken']が、index.phpで送ったものと違う値になっている
・login.phpで更新すると$_SESSION['securityLevel']の中だけ更新されるためそれが原因と考えている
該当のソースコード
index.php
<?php require_once './_header.php'; // 配列初期化 $strErrMsg = []; $_SESSION['loginUser'] = []; $_SESSION['csrfToken'] = []; $_SESSION['securityLevel'] = []; ?> <div class="login"> <form class="login__form" method="POST" action="login.php"> <h1 class="login__title">サンプルシステム</h1> <div class="login__list"> <dl class="login__item"> <dt class="login__name">ログインID</dt> <dd class="login__input"> <input type="text" id="loginID" name="loginID"> </dd> </dl> <dl class="login__item"> <dt class="login__name">パスワード</dt> <dd class="login__input"> <input type="text" id="password" name="password"> </dd> </dl> </div> <!-- ワンタイムトークン --> <input type="hidden" name="csrfToken" value="<?php echo h(setToken()); ?>"> <button class="login__button" type="submit">ログイン</button> </form> </div>
security.php
<?php /** * XSS対策:エスケープ処理 * @param string $str * @return string $処理された文字列 */ function h($str) { return htmlspecialchars($str, ENT_QUOTES, 'UTF-8'); } /** * CSRF対策 * @param void * @return string $csrfToken */ function setToken() { $csrfToken = bin2hex(random_bytes(32)); $_SESSION['csrfToken'] = $csrfToken; return $csrfToken; } ?>
login.php
<?php require_once './_header.php'; // トークンがあれば変数に入れる $token = filter_input(INPUT_POST, 'csrfToken'); var_dump($_SESSION); var_dump($token); ?>
_header.php
<?php session_start(); require_once './security.php'; // notice以外のエラーを表示 error_reporting(E_ALL & ~ E_NOTICE); ini_set("display_errors", 1); ?>
試したこと
・index.phpにワンタイムトークン等の記述
・変数にh(setToken());を入れてから使用
補足情報(FW/ツールのバージョンなど)
上記画像がlogin.phpでvar_dumpした結果です。
配列が$_SESSION、最後のstringが$tokenです。
ローカルでは正常に作動していましたが、サーバーに上げるとうまく機能しなくなりました。
PHP: 8.1.12
レンタルサーバー: ロリポップ
あなたの回答
tips
プレビュー