ここから本文です

練習で簡易掲示板を作成中です。書き込み、投稿、表示はできるのですが、F5を押...

ちゃむちゃむさん

2013/7/1714:55:50

練習で簡易掲示板を作成中です。書き込み、投稿、表示はできるのですが、F5を押した時に、内容をもう一度投稿し実行します。という注意が出ます。現段階では、二重投稿が起きてしまうので

これを、防ぐようにしたいのですが、どのように指示を書き込めばいいのかわからないのです。
勉強を始めたばかりで知識もあまりないので、お手柔らかに教えていただけるとありがたいです。

テスト環境は、レンタルサーバを利用してアップロードしたりして確認をしています。
バージョン等の細かい記載をしていなくて申し訳ないです;

念のためコード載せます

<html>
<head>
<title>ミニ掲示</title>
</head>
<body>
<div Align="center"><h1>~ミニ掲示~</h1>
</div>
<hr>
<br>

<div align="center">
<form method="post" action="c_minikeiji.php" >
<label for="personal_name">お名前 : </label>
<input type="textarea" cols="50" rows="7" name="personal_name"><br><br>
<label for="comment">内容 : </label>
<input type="textarea" cols="50" rows="7" name="comment">
<input type="submit" name="btn1" value="投稿する" />

</form>
</div>


<div align="center"><?php
//date_default_timezone_set('Asia/Tokyo');
print('現在は ' . date ('Y/m/d G:i:s') . ' です');
?></div>
<hr>

<ul>
<?php
if ($_POST['personal_name'] && $_POST['personal_name'] != '')
{
// ファイルをオープンする命令
// 1つ目はオープンするファイル名
// 2つ目はオープンする属性 a:書き込み(ファイルの最後に書き込む)
// wというのもあるけどファイルを初期化してしまい追記されていかない。
$fp = fopen('./save/data.txt', 'a');
// オープンに成功していたらという判定
if ($fp) {
// オープンしたファイルに書き込む(改行も追加)
fputs($fp, $_POST['personal_name']."###".$_POST['comment']."###".date('Y/m/d G時 i分 s秒')."\n");
// オープンしたらクローズする
fclose($fp);
}
}
?>

<?php
// ファイルをオープンする命令
// rは読み込み専用
$fp = fopen("./save/data.txt", "r");
// オープンに成功していたらという判定
while ($str = fgets($fp)) {
if($str == '')next();
$list[] = $str;
}
fclose($fp);

if ($list) {
$list = array_reverse($list);
foreach ($list as $str) {
//explode:文字列を文字列により分割する
$strs = explode("###",$str);

$name = $strs[0];
$comment = $strs[1];
$datetime = $strs[2];

echo "<li>$name [ $datetime ]</li>";
echo "<div>$comment</div>";

}
}

?>

</ul>
</body>

補足みなさま回答ありがとうございます。
ファイルの処理については、覚えるということで処理を実行するようにしてみました。
使わないと覚えなさそうなので><
そのほかのご指摘もありがとうございます。
一つずつ覚えていこうと思います。
まずは二重投稿を防がなくては><
これからもちょこちょこ質問するかもしれませんがよろしくおねがいします。
いつもアドバイス頂けること感謝しております。

閲覧数:
556
回答数:
4

違反報告

ベストアンサーに選ばれた回答

agu********さん

2013/7/1715:55:04

majiyagichanさん

「php ワンタイムチケット」で検索するといいかもしれません

(例)
http://chibitcpu.blogspot.jp/2011/11/php22.html

この回答は投票によってベストアンサーに選ばれました!

ベストアンサー以外の回答

1〜3件/3件中

並び替え:回答日時の
新しい順
|古い順

si_********さん

2013/7/1900:28:10

再度ページへ飛ばせば?

プロフィール画像

カテゴリマスター

mpywさん

編集あり2013/7/1720:08:05

(一応以前の質問へのリンク)
http://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q1111007225...

F5での2重投稿を防止するにはワンタイムトークンの利用が不可欠です。
同時にこれはCSRF対策としても貢献してくれます。

以前提示したサンプルにちょっと付け足してみます。↓

PHP - Twitter風(?)な匿名ひとこと掲示板サンプル
(Qiita) http://qiita.com/mpyw/items/e7f3f60b687053b7832a

「名前」の欄が無いですが、これを付け足すことは容易に出来るでしょう。


● 提示されたソースコードの問題点

1. 上で述べたようにワンタイムトークンがなく、F5リロードやCSRFの対策をしていない。

2. POSTされているかどうかの判断は、isset構造を使って行う。if ($_POST[…]) { } ではダメ。
http://qiita.com/mpyw/items/2f9955db1c02eeef43ea

3. 「###」という文字列が投稿されたときを考慮していない。素直にfputcsv/fgetcsv関数に頼るのが良いと思う。
http://php.net/manual/ja/function.fputcsv.php
http://www.php.net/manual/ja/function.fgetcsv.php

4. わざわざファイルを「a」と「w」に分けて2回もオープンする必要が無く、「a+」とrewind関数を利用して、書き込みと読み込みを同時に行えばいい。その際、書き込み中のみ排他ロックを行う。
http://php.net/manual/ja/function.fopen.php
http://php.net/manual/ja/function.rewind.php

5. htmlspecialchars関数を通していないため、<script>タグを埋め込まれたときにJavaScriptを勝手に実行されたりと、XSS脆弱性が存在する。
http://www.websec-room.com/2013/03/19/636


手厳しい意見を書いちゃったような感じがありますが、勉強を始めたばかりとは思えないぐらい飲み込みは良い方だと感じます。
これからも学習を続けていってください。応援しています。

蛇足ですが、PHP開発の際はE_NOTICEを含むすべてのエラーを出力する状態で実行されることをオススメしておきます。
きれいなコードを書くためには不可欠です。
http://blog.thingslabo.com/archives/000184.html

レンタルサーバーだとphp.iniはいじれないので、これをスクリプト頭に実行してください。

ini_set('display_errors', '1');
error_reporting(E_ALL);

プロフィール画像

カテゴリマスター

tezcelloさん

2013/7/1716:56:12

二重投稿をチェックするだけなら、無条件に投稿内容(ポストされたデータ)をファイルに書き出すのではなく、同じ内容の投稿があるかをチェックしてから書き込めばよいでしょう。

簡単にやるなら、最終の投稿との比較で大方はOKでしょう。
チャンとやるなら、一旦全データを読み込んで(あるいは行毎に読み込んで全行を)チェックすれば二重投稿を防ぐのは可能ですよね?

他にも
投稿内容は一旦SESSIONに書き出しておいて、確認ページを経由してから実際にファイルへ書き出すと同時にSESSIONはクリアしておき、確認ページの表示時はSESSIONのデータがある時だけ表示する

なんて方法でも簡単な二重投稿防止が可能でしょう。



1人でテストしているうちは全く問題にならないでしょうが、複数のアクセスがある場合に備えるファイルのロックとか、
悪意のあるユーザからの悪意のある書込みへの対処として、htmlspecialchars() の利用とかも勉強されるといいと思います。

みんなで作る知恵袋 悩みや疑問、なんでも気軽にきいちゃおう!

Q&Aをキーワードで検索:

Yahoo! JAPANは、回答に記載された内容の信ぴょう性、正確性を保証しておりません。
お客様自身の責任と判断で、ご利用ください。
本文はここまでです このページの先頭へ

「追加する」ボタンを押してください。

閉じる

※知恵コレクションに追加された質問は選択されたID/ニックネームのMy知恵袋で確認できます。

不適切な投稿でないことを報告しました。

閉じる