###質問内容
macのVScodeで$_SESSION["token"]を利用した簡単な掲示板をドットインストールの動画をお手本に作っています。
テーマが
「トークンの仕込むことによって、CSRF攻撃を防御する」
とのことなのですが、上手くいきません。
<編集部分>
初期画面はこのようになっており
Postボタンでレスlt。php画面に行くとこのようになり
Go backボタンで文字が保存されるといった感じになっています。
//////////
コードを何度も見比べたのですが、間違っている場所がわかりません。
フォルダ、ファイルは下のような感じです。
自分で試してみたところ
"../app/functions.php"ファイルを少しいじってみると
if分の条件となっている場所について、
empty($_SESSION["token"]) || $_SESSION["token"] !== filter_input(INPUT_POST, "token")
の場合はどんな値でも、全て
validateToken()のexit("Invalid post request")によるInvalid post requestが下のように表示されてしまいますが
条件部分を empty($_SESSION["token"])のみに変えてみると
上手く機能することから
$_SESSION["token"] !== filter_input(INPUT_POST, "token")
の部分が間違っているのだと思います。
さらに"../app/index.php"をブラウザにあげた初期画面について検証してみると
のドラッグ部分にあるように
編集前:value
編集後:index.phpの5行目辺り、createToken()
が上手く機能してることも考えると条件部分の
filter_input(INPUT_POST, "token")が上手く前のindex.phpファイルからデータを所得していない?のかと思います
ただそうだとしても間違っている箇所は分かりませんでした。よろしくお願いします。
下に自分のコードとドットインストールのコード比較機能画面を載せておきたいと思います。
###自分のコード
INDEX.PHP
PHP
1 <?php 2 require("../app/functions.php"); 3 createToken(); 4 define("FILENAME","../app/messages.txt"); 5 6 if($_SERVER["REQUEST_METHOD"] === "POST"){ 7 validateToken(); 8 $message = trim(filter_input(INPUT_POST, "message")); 9 $message = $message !== "" ? $message : "..."; 10 $fp = fopen(FILENAME, "a"); 11 fwrite($fp,$message."\n" ); 12 fclose($fp); 13 14 header("Location: http://localhost:8080/result.php"); 15 exit; 16} 17 $messages = file(FILENAME, FILE_IGNORE_NEW_LINES); 18 include("../app/_parts/_header.php"); 19?> 20 21<ul> 22 <?php foreach($messages as $message): ?> 23 <li><?= h($message); ?> </li> 24 <?php endforeach; ?> 25</ul> 26 27<form action="" method="post"> 28 <input type="text" name="message"> 29 <button>Post</button> 30 <input type="hidden" name="token" value="<?= h($_SESSION["token"]); ?> "> 31</form> 32 33 34<?php 35 36include("../app/_parts/_footer.php"); 37コード
functions.php
PHP
1<?php 2 3 4 function h($str){ 5 return htmlspecialchars($str, ENT_QUOTES,"UTF-8"); 6 } 7 8 function createToken(){ 9 if(!isset($_SESSION["token"])){ 10 $_SESSION["token"] = bin2hex(random_bytes(32)); 11 } 12 } 13 14 function validateToken(){ 15 if( 16 empty($_SESSION["token"]) || $_SESSION["token"] !== filter_input(INPUT_POST, "token") 17 ){ 18 exit("Invalid post request"); 19 } 20 } 21 22 session_start(); 23コード
PHP
1<?php 2 require("../app/functions.php"); 3 4 5 include("../app/_parts/_header.php"); 6?> 7<p>Message added!</p> 8<p><a href="index.php">Go back</a></p> 9 10<?php 11 12include("../app/_parts/_footer.php"); 13コード
###dottoinstallとのコード比較写真
下はresult.php
###解決方法、追記
あまり慣れない作業なので時間結構かかりましたが、分かりました笑
結論から言うと
<input type="hidden" name="token" value="<?= h($_SESSION["token"]); ?> ">
の?> ">の部分を?>"> (空白をなくす)ことで解決しました。つまり
<input type="hidden" name="token" value="<?= h($_SESSION["token"]); ?> ">
<input type="hidden" name="token" value="<?= h($_SESSION["token"]); ?>">(最後のみ変化)
をすることで上手く機能します。
あまり良くない記述ですが
value="<?= h($_SESSION["token"]); ?>"
のようにダブルクォーテーションを連続で使ったとしても、一様機能的には問題ありませんでした
尚、今回の場合はドットインストールの比較対象と自分の間違いコードを入れたり外したり、繋いだりすることでデバック(?)をやっていきました
回答2件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2021/10/27 23:36
2021/10/28 02:29
2021/10/28 08:03
2021/10/28 08:18 編集