ユーザーがEnter
2 回押すと、投稿が 2 回挿入されることがあります。
同じ投稿が既に存在するかどうかを確認する以外に、これを防ぐ解決策はありtitle
ますcontent
か?
ユーザーがEnter
2 回押すと、投稿が 2 回挿入されることがあります。
同じ投稿が既に存在するかどうかを確認する以外に、これを防ぐ解決策はありtitle
ますcontent
か?
この問題にはいくつかの解決策があります。
Javascript を使用して、投稿時にフォームの送信ボタンを無効にします。これの欠点は、これが絶対に確実な方法ではないことです。実際にボタンをクリックせずにフォームを送信するのは非常に簡単ですが、これは JavaScript が無効になっているユーザーには機能しません。私は絶対にこの方法をお勧めしません。
例:
<script language="javascript">
<!--
function disableSubmitButton() {
// you may fill in the blanks :)
}
-->
</script>
<form action="foo.php" method="post">
<input type="text" name="bar" />
<input type="submit" value="Save" onclick="disableSubmitButton();">
</form>
PHP セッションを使用して、セッション変数 ($_SESSION['posttimer'] など) を投稿時の現在のタイムスタンプに設定します。PHP でフォームを実際に処理する前に、$_SESSION['posttimer'] 変数が存在するかどうかを確認し、特定のタイムスタンプの差 (IE: 2 秒) を確認します。このようにして、二重送信を簡単に除外できます。
例:
// form.html
<form action="foo.php" method="post">
<input type="text" name="bar" />
<input type="submit" value="Save">
</form>
// foo.php
if (isset($_POST) && !empty($_POST))
{
if (isset($_SESSION['posttimer']))
{
if ( (time() - $_SESSION['posttimer']) <= 2)
{
// less then 2 seconds since last post
}
else
{
// more than 2 seconds since last post
}
}
$_SESSION['posttimer'] = time();
}
各 POST に一意のトークンを含めます。この場合、含めるトークンにセッション変数を設定し、トークンをフォームにレンダリングします。フォームが送信されたら、トークンを再生成します。送信されたトークンがセッションのトークンと一致しない場合、フォームは再送信されており、無効であると宣言する必要があります。
例:
// form.php
<?php
// obviously this can be anything you want, as long as it is unique
$_SESSION['token'] = md5(session_id() . time());
?>
<form action="foo.php" method="post">
<input type="hidden" name="token" value="<?php echo $_SESSION['token'] ?>" />
<input type="text" name="bar" />
<input type="submit" value="Save" />
</form>
// foo.php
if (isset($_SESSION['token']))
{
if (isset($_POST['token']))
{
if ($_POST['token'] != $_SESSION['token'])
{
// double submit
}
}
}
投稿で一意のトークンを使用して、各投稿/ポストバックが 1 回だけ処理されるようにします。
送信ボタンを無効にすることはあまり良い解決策ではありません。なぜなら、人々は JavaScript をオフにしたり、他の奇妙なことをしたりする可能性があるからです。クライアント側の検証は良い出発点ですが、サーバー側の処理も常にバックアップする必要があります。
フォームで送信するための一意の1回限りの使用キーを生成します。
Javascriptに依存することは、ユーザーによってクライアントで無効にされている可能性があるため、お勧めできません。キースキームを使用すると、サーバーが送信を受信したときに、そのキーの送信をロックできます。重複した送信には、好きなように返信できます。
このアプローチが機能するためには、キーが一意であり、予測が非常に難しい必要があります。そうしないと、キーの衝突が原因で一部のフォームがロックされる可能性があります。したがって、フォームの送信ごとにキーを追跡して衝突を回避する必要はありません。キーはそのユーザーのセッションで期限切れになるはずです。もう1つの注意点は、悪意のあるユーザーがキーを予測できる場合、コードが何らかのハイジャックやDOSエクスプロイトに対して脆弱である可能性があることです。
重複フォーム送信の防止は、javascript を使用せずにそれを行う方法を示しています。
または、ワンタイムフォームキーを使用します。
私はこれを使用します:
$form_token = $_SESSION['form_token'] = md5(uniqid());
フォームで $form_token を送信してから...
form_token を確認します。
if($_SESSION['form_token'] != $_POST['form_token']) {
echo 'Error';
}
フォームが送信されたら、Javascript を使用して送信ボタンを無効にします ( onsubmit
)。
ユーザーが Javascript を無効にしている場合でも、2 回送信できることに注意してください。(質問で提案したように)コードをチェックインすることを正当化するのに十分な頻度でこれが発生するかどうかは、あなた次第です。
送信を 2 回押しても、複数の挿入が行われることはめったにありませんが、非常に単純な解決策が必要な場合は、
onsubmit="document.getElementById('submit').disabled = true"
フォームタグで、送信ボタンを指定する場合id="submit"
ユーザーがフォームを送信したら、JavaScript を使用して送信ボタンを無効にします。これは、たとえば、質問に答えるときに StackOverflow が使用するものです。
例えば
<input type="submit" onclick="this.disabled=true" />
JavaScript を使用して、クリックするとすぐにボタンを無効にします。
onclick="this.disabled=true;forms[0].submit();"
私はaction.phpで次のことをやっています
if($_SESSION && isset($_SESSION['already_submitted'])) {
# If already submitted just redirect to thank you page
} else {
# If first submit then assign session value and process the form
$_SESSION['already_submitted'] = true;
# Process form
}
注: session_start(); を使用して、常にヘッダーでセッションを開始します。
JavaScript を使用して送信を停止する
Aron Rotteveel のInclude a unique token 各 POSTは私にとってはうまくいきました。ただし、ユーザーがページを更新 (F5) すると、フォームは引き続き送信されます。リセットを追加することでこれを解決できました:
// reset session token
$_SESSION['token'] = md5( $_POST['token'] . time() );
私の最終的なスクリプトは次のようになります:
if (isset($_SESSION['token'])) {
if (isset($_POST['token'])) {
if ($_POST['token'] != $_SESSION['token']) {
echo '<h3>Oops! You already submitted this request.</h3>';
} else {
// process form
// reset session token
$_SESSION['token'] = md5( $_POST['token'] . time() );
}
} else {
echo 'post token not set';
$_SESSION['token'] = md5( $somevariable . time() );
}
}
おー!session_start();
前に追加することを忘れないでください<!DOCTYPE>
私はPHPの初心者なので、不規則性を見つけたら修正してください。
$(document).ready(function() {
$('#postHideBtn').show();
$('#postHideBtn').click(function() {
$('#postHideBtn').hide();
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form action="foo.php" method="post">
<input type="text" name="bar" />
<input type="submit" value="Save" id="postHideBtn" />
</form>