Php 如何在刷新页面时防止表单重新提交(F5/CTRL+;R)
我有一个简单的表单将文本提交到我的SQL表。问题是,在用户提交文本后,他们可以刷新页面并再次提交数据,而无需再次填写表单。提交文本后,我可以将用户重定向到另一个页面,但我希望用户保持在同一页面上Php 如何在刷新页面时防止表单重新提交(F5/CTRL+;R),php,html,forms,post,form-submit,Php,Html,Forms,Post,Form Submit,我有一个简单的表单将文本提交到我的SQL表。问题是,在用户提交文本后,他们可以刷新页面并再次提交数据,而无需再次填写表单。提交文本后,我可以将用户重定向到另一个页面,但我希望用户保持在同一页面上 我记得读过一些关于给每个用户一个唯一的会话id并将其与另一个值进行比较的文章,该值解决了我遇到的问题,但我忘记了它在哪里。处理表单时,您会重定向到另一个页面: ... process complete.... header('Location: thankyou.php'); 您还可以重定向到同一页面
我记得读过一些关于给每个用户一个唯一的会话id并将其与另一个值进行比较的文章,该值解决了我遇到的问题,但我忘记了它在哪里。处理表单时,您会重定向到另一个页面:
... process complete....
header('Location: thankyou.php');
您还可以重定向到同一页面
如果您正在执行类似于注释的操作,并且希望用户保持在同一页面上,那么可以使用Ajax处理表单提交使用Post/Redirect/Get模式
使用我的网站,我将在cookie或会话中存储消息,在发布后重定向,读取cookie/会话,然后清除该会话或cookie变量的值。为什么不将
$\u post['submit']
变量用作逻辑语句来保存表单中的内容呢。您始终可以重定向到同一页面(以防它们刷新,并且当它们在浏览器中点击返回
时,将不再设置submit post变量。只需确保您的submit按钮具有名称
和id
的提交
标题(“Location:your_page.php”);
您可以重定向到同一页面或不同页面unset($\u POST);
您确实应该使用Post Redirect Get模式来处理此问题,但如果您最终遇到PRG不可行的情况(例如,表单本身在包含中,阻止重定向),您可以散列一些请求参数,以根据内容生成字符串,然后检查您是否已经发送了该字符串
//create digest of the form submission:
$messageIdent = md5($_POST['name'] . $_POST['email'] . $_POST['phone'] . $_POST['comment']);
//and check it against the stored value:
$sessionMessageIdent = isset($_SESSION['messageIdent'])?$_SESSION['messageIdent']:'';
if($messageIdent!=$sessionMessageIdent){//if its different:
//save the session var:
$_SESSION['messageIdent'] = $messageIdent;
//and...
do_your_thang();
} else {
//you've sent this already!
}
在使用表单数据后,只需将其重定向到同一页面,它就可以工作了。我已经尝试过了
header('location:yourpage.php');
一个非常可靠的方法是在post中实现一个唯一的ID,并将其缓存在
<input type='hidden' name='post_id' value='".createPassword(64)."'>
然后在代码中执行以下操作:
if( ($_SESSION['post_id'] != $_POST['post_id']) )
{
$_SESSION['post_id'] = $_POST['post_id'];
//do post stuff
} else {
//normal display
}
function createPassword($length)
{
$chars = "abcdefghijkmnopqrstuvwxyz023456789";
srand((double)microtime()*1000000);
$i = 0;
$pass = '' ;
while ($i <= ($length - 1)) {
$num = rand() % 33;
$tmp = substr($chars, $num, 1);
$pass = $pass . $tmp;
$i++;
}
return $pass;
}
if($\u会话['post\u id']!=$\u post['post\u id']))
{
$\u会话['post\u id']=$\u post['post\u id'];
//发邮件
}否则{
//正常显示
}
函数createPassword($length)
{
$chars=“abcdefghijkmnopqrstuvxyzo23456789”;
srand((双)微时间()*1000000);
$i=0;
$pass='';
而($i是Moob帖子的精练版本。创建帖子的散列,将其保存为会话cookie,并在每个会话中比较散列
// Optionally Disable browser caching on "Back"
header( 'Cache-Control: no-store, no-cache, must-revalidate' );
header( 'Expires: Sun, 1 Jan 2000 12:00:00 GMT' );
header( 'Last-Modified: ' . gmdate('D, d M Y H:i:s') . 'GMT' );
$post_hash = md5( json_encode( $_POST ) );
if( session_start() )
{
$post_resubmitted = isset( $_SESSION[ 'post_hash' ] ) && $_SESSION[ 'post_hash' ] == $post_hash;
$_SESSION[ 'post_hash' ] = $post_hash;
session_write_close();
}
else
{
$post_resubmitted = false;
}
if ( $post_resubmitted ) {
// POST was resubmitted
}
else
{
// POST was submitted normally
}
将其插入数据库后,调用unset()方法清除数据
unset($\u POST);
要防止插入刷新数据,请在插入记录后将页面重定向到同一页面或不同页面
标题('Location:'.$\u SERVER['PHP\u SELF']);基本上,您需要重定向出该页面,但当您的internet速度较慢时,仍然会出现问题(从服务器端重定向标题)
基本场景示例:
点击提交按钮两次
解决方法
- 客户端
- 客户端单击“提交”按钮后禁用该按钮
- 如果您使用Jquery:
- 服务器端
- 发送请求时使用基于区分的哈希时间戳/时间戳
- Userequest令牌。当主服务器加载时,将临时请求分配给令牌,如果重复,则忽略该请求
使用Keverw答案的Post/Redirect/Get模式是一个好主意。但是,您无法停留在您的页面上(我认为这就是您所要求的?),此外,有时可能:
如果web用户在首次提交完成之前刷新
由于服务器延迟,导致中出现重复的HTTP POST请求
某些用户代理
另一种选择是,如果文本应该像这样写入SQL数据库,则将其存储在会话中:
if($_SERVER['REQUEST_METHOD'] != 'POST')
{
$_SESSION['writeSQL'] = true;
}
else
{
if(isset($_SESSION['writeSQL']) && $_SESSION['writeSQL'])
{
$_SESSION['writeSQL'] = false;
/* save $_POST values into SQL */
}
}
if(isset($_POST['submitbtn']) && $_POST['randcheck']==$_SESSION['rand'])
{
// Your code here
}
if ( !empty($_SESSION['act']) && !empty($_POST['act']) && $_POST['act'] == $_SESSION['act'] ) {
// do your stuff, save data into database, etc
}
$cat process.php
<?php
process POST data here
...
header('Location: /the/result/page');
exit();
?>
您可以通过会话变量阻止表单重新提交
首先,您必须在文本框中设置rand()
,并在表单页面上设置$\u会话['rand']
:
<form action="" method="post">
<?php
$rand=rand();
$_SESSION['rand']=$rand;
?>
<input type="hidden" value="<?php echo $rand; ?>" name="randcheck" />
Your Form's Other Field
<input type="submit" name="submitbtn" value="submit" />
</form>
确保在使用会话的每个文件上启动会话,并使用session\u start()
我还想指出,您可以使用javascript方法window.history.replaceState
来防止刷新时重新提交和返回按钮
<script>
if ( window.history.replaceState ) {
window.history.replaceState( null, null, window.location.href );
}
</script>
如果(window.history.replaceState){
window.history.replaceState(null,null,window.location.href);
}
此处的概念证明:
我仍然建议使用Post/Redirect/Get方法,但这是一种新颖的JS解决方案。如何防止php表单在没有重定向的情况下重新提交。如果您使用$\u会话(会话启动后)和$\u Post表单,您可以执行以下操作:
if($_SERVER['REQUEST_METHOD'] != 'POST')
{
$_SESSION['writeSQL'] = true;
}
else
{
if(isset($_SESSION['writeSQL']) && $_SESSION['writeSQL'])
{
$_SESSION['writeSQL'] = false;
/* save $_POST values into SQL */
}
}
if(isset($_POST['submitbtn']) && $_POST['randcheck']==$_SESSION['rand'])
{
// Your code here
}
if ( !empty($_SESSION['act']) && !empty($_POST['act']) && $_POST['act'] == $_SESSION['act'] ) {
// do your stuff, save data into database, etc
}
$cat process.php
<?php
process POST data here
...
header('Location: /the/result/page');
exit();
?>
在html表单中输入以下内容:
<input type="hidden" id="act" name="act" value="<?php echo ( empty($_POST['act']) || $_POST['act']==2 )? 1 : 2; ?>">
<?php
if ( $_POST['act'] == $_SESSION['act'] ){
if ( empty( $_SESSION['act'] ) || $_SESSION['act'] == 2 ){
$_SESSION['act'] = 1;
} else {
$_SESSION['act'] = 2;
}
}
?>
我找到了下一个解决方法。在处理POST
请求后,您可以通过操纵对象来逃避重定向
因此,您有了HTML表单:
<form method=POST action='/process.php'>
<input type=submit value=OK>
</form>
处理POST
ed数据后,您将呈现较小的
和结果/result/page
<?php
process POST data here
render the <script> // see below
render `/the/result/page` // OK
?>
您应该呈现的
:
<script>
window.onload = function() {
history.replaceState("", "", "/the/result/page");
}
</script>
window.onload=函数(){
replaceState(“,”,“/the/result/page”);
}
结果是:
如您所见,表单数据是POST
ed到process.php
script。
此脚本处理POST
ed数据并立即呈现/result/page
,包括:
无重定向
刷新页面(F5)时无rePOST
数据
在浏览器历史记录中导航到上一页/下一页时,无rePOST
UPDif ( !refreshed()) {
//Your Submit Here
if (isset( $_GET['refresh'])) {
setcookie("refresh",$_GET['refresh'], time() + (86400 * 5), "/");
}
}
}
function refreshed()
{
if (isset($_GET['refresh'])) {
$token = $_GET['refresh'];
if (isset($_COOKIE['refresh'])) {
if ($_COOKIE['refresh'] != $token) {
return false;
} else {
return true;
}
} else {
return false;
}
} else {
return false;
}
}
function createToken($length) {
$characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
$charactersLength = strlen($characters);
$randomString = '';
for ($i = 0; $i < $length; $i++) {
$randomString .= $characters[rand(0, $charactersLength - 1)];
}
return $randomString;
}
?>
<form action="?refresh=<?php echo createToken(3)?>">
</form>
<?php
session_start();
function doSelfRedirect()
{
header('Location:'.$_SERVER['PHP_SELF']);
exit;
}
function setFlashMessage($msg)
{
$_SESSION['message'] = $msg;
}
function getFlashMessage()
{
if (!empty($_SESSION['message'])) {
$msg = $_SESSION['message'];
unset($_SESSION['message']);
} else {
$msg = null;
}
return $msg;
}
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
// Validation primitive example.
if (empty($_POST['valid'])) {
$formIsValid = false;
setFlashMessage('Invalid form submit');
} else {
$formIsValid = true;
}
if ($formIsValid) {
// Perform any actions here.
// ...
// Cool!
setFlashMessage('Form is valid. Action performed.');
// Prevent form resubmission.
doSelfRedirect();
}
}
?>
<h1>Hello form</h1>
<?php if ($msg = getFlashMessage()): ?>
<div><?= $msg ?></div>
<?php endif; ?>
<form method="post">
<input type="text" name="foo" value="bar"><br><br>
<button type="submit" name="invalid" value="0">Invalid submit</button>
<button type="submit" name="valid" value="1">Valid submit</button>
</form>