質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.46%
CSS3

CSS(Cascading Style Sheet)の第3版です。CSS3と略されることが多いです。色やデザインを柔軟に変更することが可能になります。

HTML5

HTML5 (Hyper Text Markup Language、バージョン 5)は、マークアップ言語であるHTMLの第5版です。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Q&A

解決済

3回答

296閲覧

リロードによる多重投稿を防げない

gakut

総合スコア2

CSS3

CSS(Cascading Style Sheet)の第3版です。CSS3と略されることが多いです。色やデザインを柔軟に変更することが可能になります。

HTML5

HTML5 (Hyper Text Markup Language、バージョン 5)は、マークアップ言語であるHTMLの第5版です。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

0グッド

1クリップ

投稿2024/05/08 01:49

実現したいこと

webサイトの掲示板にて、リロードによるコメントデータの登録が多重に行われることの防止策を実現したいです。

発生している問題・分からないこと

HTML①のformにて、テキストエリアの入力値(コメント)と、そのコメントを投稿しようとする掲示板のidを、submitボタンを押すことで/write_redirectに渡します。次に、そこでログインの有無を確認した上で、ログインしていればrequestを使ってsessionに受信したta, idを設定し、/writeにリダイレクトします。/writeにてtaとidをsessionから取り出し、save_chat_appendでtaを当idの掲示板データファイル(json)に書き込み、書き込み後の当データファイルのチャットデータを読み込み、それを掲示板htmlに必要なデータとして渡すことで投稿後のチャット履歴を掲示板に表示します。今当たっているのは、この投稿処理後に、その掲示板をリロードで再読み込みすると何故か投稿した同データが再投稿される問題です。タイトルの通り、いくら防止策を探しても下記のPRGパターン以外に適用できそうなものがなく、そのPRGパターンをもってしても多重投稿がなくなりません。

該当のソースコード

Python①

1@app.route('/write') 2def write(): 3 ta = session['ta'] 4 id = session['id'] 5 if ta == '': return show_msg('書込が空でした') 6 bbs_chat_data.save_chat_append(id, bbs_login.get_user(), ta) 7 chat_data = bbs_chat_data.load_chat(id) 8 return render_template('thread.html', 9 detail=chat_data[-1], chat=chat_data[0:len(chat_data)-1], id=id) 10 11@app.route('/write_redirect', methods=['POST']) 12def write_redirect(): 13 if not bbs_login.is_login(): 14 return redirect('/login') 15 session['ta'] = request.form.get('ta', '') 16 session['id'] = request.args.get('id', None) 17 return redirect('/write')

HTML①

1<!DOCTYPE html> 2<html><meta charset="UTF-8"> 3 <meta name="viewport" 4 content="width=device-width, initial-scale=1.0"> 5 <link rel="stylesheet" href="static/css/pure-min.css"> 6 <link rel="stylesheet" href="static/css/style.css?v=0220"> 7 <body><div class="content"> 8 <!-- 書き込みフォーム --> 9 <h1>{{ detail.title }} - {{ detail.date }} by {{ detail.wname }}</h1> 10 <form action="/write_redirect?id={{ id }}" method="POST" 11 class="pure-form pure-form-stacked"> 12 <textarea name="ta" rows="4" cols="60"></textarea> 13 <button type="submit" 14 class="pure-button pure-button-primary"> 15 書き込む</button> 16 </form> 17 <!-- 掲示板のログを表示する --> 18 {% for i in chat %} 19 <div class="box"> 20 <p class="box_h">{{ i.name }} - {{ i.date }}</p> 21 <p>{{ i.text }}</p> 22 </div> 23 {% endfor %} 24</div></body></html>

試したこと・調べたこと

  • teratailやGoogle等で検索した
  • ソースコードを自分なりに変更した
  • 知人に聞いた
  • その他
上記の詳細・結果

上述の通り、PRGパターンを導入することで、最後に送信されたのがPOSTではなくGETリクエストになりました。これで解決したかと思いきや、まだリロードでデータが多重登録されてしまいます。他の防止策はphpが主なので採用しようにも採用できません(htmlファイルにはhtmlとjavascript, jQueryしか使っていないので採用できるか分かりません)。

補足

フレームワークはflaskを使っています。OSはWindowsです。ページのcssにはpure-min.css, style.cssを使っており、リロード時に毎回読み込んでいます。

投稿時の通信内容は下記の通りです。
127.0.0.1 - - [08/May/2024 05:30:53] "POST /write_redirect?id=1 HTTP/1.1" 302 -
127.0.0.1 - - [08/May/2024 05:30:53] "GET /write HTTP/1.1" 200 -
127.0.0.1 - - [08/May/2024 05:30:53] "GET /static/css/pure-min.css HTTP/1.1" 304 -
127.0.0.1 - - [08/May/2024 05:30:53] "GET /static/css/style.css?v=0220 HTTP/1.1" 304 -

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yambejp

2024/05/08 01:55

pythonの他にPHPのタグ付けがあるのですが、サーバー環境は選択肢があるということでしょうか?
gakut

2024/05/08 06:00

もしかしたらPHPを利用した解決案が出るかもしれないと思い、タグ付けしました。PHPってjavascriptとは同時に取り扱えない感じですか?
juner

2024/05/08 06:23

PHP はサーバーサイドの言語なので Pythonと同時に扱えないの方ですね。
gakut

2024/05/08 06:36

分かりました。
guest

回答3

0

ベストアンサー

リダイレクト後の GET /write でデータを書き込んでおり、かつセッションデータも削除していないので、リロードすると再書き込みされているのかと思います。

GET /write ではなく、 POST /write_redirect でデータを書き込んだあとでリダイレクトしましょう。
GETリクエストでのデータ変更は通常行うべきではありません。

投稿2024/05/08 02:58

Eggpan

総合スコア2810

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

gakut

2024/05/08 05:33

回答ありがとうございます。 試したところ問題が解決しました! GETとPOSTの役割は完全に分割しないといけないんですね。 GETとPOSTの使い分けについての理解が深まりました!
guest

0

多重投稿の前にまず必ずやるべきCSRF対策が先。
CSRF対策で結果的に多重投稿もある程度防げる。
それでも連打すると多重投稿されることもあるのでJavaScriptで送信ボタンを無効化するなどの対策をする。

投稿2024/05/08 02:17

pcs

総合スコア409

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

tezcello

2024/05/08 05:50

ページ毎にCSRF対策と同じ様にトークンを使う事で多重投稿を排除する事は(100%かは確証が無いけど)可能でしょう。 その代わり、現在では当たり前になったブラウザの別タブから同じサイトのトークンを発行するページにアクセスすると、単純なトークン管理(≒ワンタイムトークン)では拒否される事になります。 しばらく前から、CSRF用のトークンはセッション毎の固定トークンで良いと言われている様なので、それに従うとCSRF対策では多重投稿を防げません。
gakut

2024/05/08 06:33

同じGETリクエストまたはPOSTリクエストを検知したら異常対策を行うのがCSRF対策ってことですよね? 固定トークンの場合、正常な送信者から正常な送信が行われた場合、トークンが毎回一致してしまうので同一の送信を複数回行っても問題ないって解釈で合ってますか?
tezcello

2024/05/08 09:39

> 同じGETリクエストまたはPOSTリクエストを検知したら異常対策を行うのがCSRF対策ってことですよね? それは CSRF対策ではないと思います。 https://ja.wikipedia.org/wiki/%E3%82%AF%E3%83%AD%E3%82%B9%E3%82%B5%E3%82%A4%E3%83%88%E3%83%AA%E3%82%AF%E3%82%A8%E3%82%B9%E3%83%88%E3%83%95%E3%82%A9%E3%83%BC%E3%82%B8%E3%82%A7%E3%83%AA > 固定トークンの場合、(略)複数回行っても問題ないって解釈で合ってますか? その解釈は合っています。 CSRF対策としてのトークンの本来の目的とは違うので、多重投稿を拒否する用途にそのまま流用できません。
guest

0

投稿はAPIを利用した非同期にして、データの受取はサーバー送信イベントで行ってはどうでしょうか?

投稿2024/05/08 01:57

yambejp

総合スコア115010

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

gakut

2024/05/08 06:09

XMLHttpRequestを使うってことですか? サーバとhtmlファイルの間でデータの送受信を非同期にする感じですね。またデータの非同期送受信が必要になるときに参考にしたいと思います!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.46%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問