CSRF対策でトークンの設定と確認をどこで行えばよいのかわかりません。
input.htmlで、名前と性別とコメントを入力し送信すると、insert.phpへと飛び、入力チェック等を行った後にDBと接続して入力データをレコードに追加します。
input.html
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="utf-8"> <title>入力画面</title> </head> <body> <form action="insert.php" method="post"> お名前: <input type="text", name="name" required> <br> 性別: <select name="sex" required> <option value="男">男</option> <option value="女">女</option> </select> <br> コメント: <textarea name="comment" cols="25" rows="4" maxlength="100" required></textarea> <br> <input type="submit" value="送信"> </form> </body> </html>
insert.phpは以下です。checkEncodingとescapeはユーザー定義関数です。
<?php $back = "input.html"; // 文字エンコードの検証 if (!checkEncoding($_POST)){ header("Location:{$back}"); exit(); } $errors = []; if (($_POST["name"]==="")||($_POST["sex"]==="")||($_POST["comment"]==="")){ $errors[] = "空です。"; }else { $name = escape($_POST["name"]); $sex = escape($_POST["sex"]); $comment = escape($_POST["comment"]); } if (count($errors) > 0){ echo "<ol>"; foreach ($errors as $value) { echo "<li>", $value , "</li>"; } echo "</ol>"; echo "<hr>"; echo "<a href=", $back, ">戻る</a>"; exit(); } $user = 'user'; $password = 'password'; $dbName = 'db'; $host = 'localhost'; $dsn = "mysql:host={$host};dbname={$dbName};charset=utf8"; ?> <!DOCTYPE html> <html lang="ja"> <head> <meta charset="utf-8"> <title>レコード追加</title> </head> <body> <?php try { $pdo = new PDO($dsn, $user, $password); $pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false); $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); $sql = "INSERT INTO member (name, sex, comment) VALUES (:name, :sex, :comment)"; $stm = $pdo->prepare($sql); $stm->bindValue(':name', $name, PDO::PARAM_STR); $stm->bindValue(':sex', $sex, PDO::PARAM_STR); $stm->bindValue(':comment', $comment, PDO::PARAM_STR); $stm->execute(); echo "投稿ありがとうございました。"; } catch (Exception $e) { echo $e->getMessage(); } ?> </body> </html>
この場合だとどこにsetToken()とcheckToken()を入れればよいでしょうか?
トークンの関数作ってみました。(もしこれが安全でなければそれも教えてください。)
function setToken(){ $bytes=openssl_random_pseudo_bytes(16); $token=bin2hex($bytes); $_SESSION['token']=$token; } function checkToken(){ if(empty($_SESSION['token']) || ($_SESSION['token']) != $_POST['token']){ echo "不正なPOSTが行われました"; exit(); } }
投稿前にsetToken()し、投稿後にcheckToken()すると聞いたのですが、ページ遷移している必要はありますか?
「投稿ありがとうございました」と表示する画面と、DBにレコードを追加する処理は別のファイルに書いたほうが良いのでしょう?
ご回答いただけたら幸いです。
回答2件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2017/09/15 06:17
2017/09/15 06:27
2017/09/15 06:41
2017/09/15 09:59 編集
2017/09/15 11:41