我有一个简单的表单,可以将文本提交到我的SQL表。问题是,在用户提交文本后,他们可以刷新页面并再次提交数据,而无需再次填写表单。我可以在提交文本后将用户重定向到另一个页面,但我希望用户留在同一页面上。
我记得读过一些关于给每个用户一个唯一会话ID并将其与另一个值进行比较的信息,这个值解决了我遇到的问题,但我忘记了它的位置。
答案 0 :(得分:76)
使用发布/重定向/获取模式。 http://en.wikipedia.org/wiki/Post/Redirect/Get
通过我的网站,我会在cookie或会话中存储消息,在帖子后重定向,读取cookie /会话,然后清除该会话或cookie变量的值。
答案 1 :(得分:52)
我还想指出,您可以使用javascript方法window.history.replaceState
来阻止重新提交刷新和后退按钮。
<script>
if ( window.history.replaceState ) {
window.history.replaceState( null, null, window.location.href );
}
</script>
这里的概念证明:https://dtbaker.net/files/prevent-post-resubmit.php
我仍然会推荐Post / Redirect / Get方法,但这是一个新颖的JS解决方案。
答案 2 :(得分:16)
你应该真正使用Post Redirect Get模式来处理这个问题,但是如果你以某种方式最终处于PRG不可行的位置(例如表单本身在include中,防止重定向)你可以哈希一些请求参数根据内容创建一个字符串,然后检查您是否已经发送过它。
//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!
}
答案 3 :(得分:12)
处理表单后,您将重定向到另一个页面:
... process complete....
header('Location: thankyou.php');
您也可以重定向到同一页面。
如果您正在执行类似评论的操作并且希望用户保持在同一页面上,则可以使用Ajax处理表单提交
答案 4 :(得分:12)
您可以通过会话变量Like
来完成表单重新提交首先你必须在文本框中设置rand()并在表单页面上设置$ _SESSION [&#39; rand&#39;]
<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>
使用文本框$ _POST [&#39; randcheck&#39;]值检查$ _SESSION [&#39; rand&#39;]后 像
if(isset($_POST['submitbtn']) && $_POST['randcheck']==$_SESSION['rand'])
{
//Your Code here
}
答案 5 :(得分:11)
使用标题并重定向页面。
header("Location:your_page.php");
您可以重定向到同一页面或不同页面。
将$ _POST插入数据库后取消设置。
unset($_POST);
答案 6 :(得分:9)
我使用此javascript行来阻止弹出式窗口,要求其在提交表单后刷新时重新提交表单。
if ( window.history.replaceState ) {
window.history.replaceState( null, null, window.location.href );
}
只需将这一行放在文件的页脚并查看魔术
答案 7 :(得分:7)
一种非常可靠的方法是在帖子中实现一个唯一的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;
}
答案 8 :(得分:7)
我找到了下一个解决方法。通过操作history
对象处理POST
请求后,您可以转义重定向。
所以你有HTML表格:
<form method=POST action='/process.php'>
<input type=submit value=OK>
</form>
当您在服务器上处理此表单时,您可以设置/the/result/page
标题,而不是将用户重定向到Location
:
$cat process.php
<?php
process POST data here
...
header('Location: /the/result/page');
exit();
?>
处理POST
个数据后,您渲染小<script>
,结果为/the/result/page
<?php
process POST data here
render the <script> // see below
render `/the/result/page` // OK
?>
你应该渲染的<script>
:
<script>
window.onload = function() {
history.replaceState("", "", "/the/result/page");
}
</script>
结果是:
您可以看到表单数据POST
为process.php
脚本
此脚本处理POST
ed数据并立即呈现/the/result/page
,其中包含:
POST
数据POST
<强> UPD 强>
作为另一种解决方案,我要求feature request Mozilla FireFox 小组允许用户设置NextPage
标头,该标头将像Location
标头一样工作并生成{{1模式过时。
简而言之。当服务器处理成功post/redirect/get
数据时:
POST
标题而不是NextPage
Location
表单数据的结果,因为它会在POST
模式中呈现GET
请求浏览器会看到post/redirect/get
标题:
NextPage
值window.location
NextPage
请求与GET
进行协商,而不是重新NextPage
表单数据我认为如果实施这将是非常好的,不会吗? POST
答案 9 :(得分:3)
在使用表单数据后,只需将其重定向到同一页面即可。我试过了。
header('location:yourpage.php');
答案 10 :(得分:3)
Moob帖子的精致版本。创建POST的哈希值,将其保存为会话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
}
答案 11 :(得分:2)
如何防止没有重定向的php表单重新提交。如果您使用$ _SESSION(在session_start之后)和$ _POST表单,您可以执行以下操作:
if ( !empty($_SESSION['act']) && !empty($_POST['act']) && $_POST['act'] == $_SESSION['act'] ) {
// do your stuff, save data into database, etc
}
在你的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;
}
}
?>
因此,每次提交表单时,都会生成一个新的行为,存储在会话中并与后期行为进行比较。
Ps:如果您使用的是Get表单,则可以使用GET轻松更改所有POST,它也可以正常运行。
答案 12 :(得分:2)
基本上,您需要重定向到该页面,但在互联网速度较慢时仍然会出现问题(从服务器端重定向标头)
基本情景示例:
解决方法
客户端
服务器端
答案 13 :(得分:2)
将数据库插入数据库后,调用unset()方法清除数据。
<强>未设置($ _ POST); 强>
要防止刷新数据插入,请在插入记录后执行页面重定向到同一页面或不同页面。
标题( '位置:'。$ _ SERVER [ 'PHP_SELF']); 强>
答案 14 :(得分:1)
$_POST['submit'] 变量在页面初始加载时不存在,并且只有在以下条件为真时才能运行 curl。
if($_POST['submit'] == "submit"){
// This is where you run the Curl code and display the output
$curl = curl_init();
//clear $post variables after posting
$_POST = array();
}
答案 15 :(得分:0)
使用Keverw答案中的Post / Redirect / Get模式是一个好主意。但是,你无法留在你的页面上(我认为这是你要求的?)此外,它有时可能会fail:
如果网络用户在初始提交完成之前刷新 由于服务器滞后,导致重复的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 */
}
}
答案 16 :(得分:0)
正如其他人所说,不可能不使用post / redirect / get。但与此同时,你可以很容易地做你想做的服务器端。
在您的POST页面中,您只需验证用户输入,但不对其进行操作,而是将其复制到SESSION数组中。然后,您再次重定向回主提交页面。您的主提交页面首先检查您正在使用的SESSION数组是否存在,如果存在,则将其复制到本地数组并取消设置。从那里你可以采取行动。
通过这种方式,您只需完成所有主要工作,即可实现您想要的目标。
答案 17 :(得分:0)
此后,我在大型项目中寻找解决方案以防止重新提交。 该代码可与$ _GET和$ _POST高度配合,并且我不能更改表单元素的行为,否则会出现无法预料的错误。 所以,这是我的代码:
<!-- language: lang-php -->
<?php
// Very top of your code:
// Start session:
session_start();
// If Post Form Data send and no File Upload
if ( empty( $_FILES ) && ! empty( $_POST ) ) {
// Store Post Form Data in Session Variable
$_SESSION["POST"] = $_POST;
// Reload Page if there were no outputs
if ( ! headers_sent() ) {
// Build URL to reload with GET Parameters
// Change https to http if your site has no ssl
$location = "https://" . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
// Reload Page
header( "location: " . $location, true, 303 );
// Stop any further progress
die();
}
}
// Rebuilt POST Form Data from Session Variable
if ( isset( $_SESSION["POST"] ) ) {
$_POST = $_SESSION["POST"];
// Tell PHP that POST is sent
$_SERVER['REQUEST_METHOD'] = 'POST';
}
// Your code:
?><html>
<head>
<title>GET/POST Resubmit</title>
</head>
<body>
<h1>Forms:</h1>
<h2>GET Form:</h2>
<form action="index.php" method="get">
<input type="text" id="text_get" value="test text get" name="text_get"/>
<input type="submit" value="submit">
</form>
<h2>POST Form:</h2>
<form action="index.php" method="post">
<input type="text" id="text_post" value="test text post" name="text_post"/>
<input type="submit" value="submit">
</form>
<h2>POST Form with GET action:</h2>
<form action="index.php?text_get2=getwithpost" method="post">
<input type="text" id="text_post2" value="test text get post" name="text_post2"/>
<input type="submit" value="submit">
</form>
<h2>File Upload Form:</h2>
<form action="index.php" method="post" enctype="multipart/form-data">
<input type="file" id="file" name="file">
<input type="submit" value="submit">
</form>
<h1>Results:</h1>
<h2>GET Form Result:</h2>
<p>text_get: <?php echo $_GET["text_get"]; ?></p>
<h2>POST Form Result:</h2>
<p>text_post: <?php echo $_POST["text_post"]; ?></p>
<h2>POST Form with GET Result:</h2>
<p>text_get2: <?php echo $_GET["text_get2"]; ?></p>
<p>text_post2: <?php echo $_POST["text_post2"]; ?></p>
<h2>File Upload:</h2>
<p>file:
<pre><?php if ( ! empty( $_FILES ) ) {
echo print_r( $_FILES, true );
} ?></pre>
</p>
<p></p>
</body>
</html><?php
// Very Bottom of your code:
// Kill Post Form Data Session Variable, so User can reload the Page without sending post data twice
unset( $_SESSION["POST"] );
它只能避免重新提交$ _POST,而不是$ _GET。但这是我需要的行为。 重新提交问题不适用于文件上传!
答案 18 :(得分:0)
JavaScript
此方法非常简单,一旦提交表单,就会阻止弹出窗口在刷新时要求重新提交表单。只需将这行javascript代码放在文件的页脚处,然后看一下魔术。
Select replace(new_variable,',','','')
From dual;
答案 19 :(得分:0)
这种方法对我来说效果很好,我认为这是完成这项工作的最简单方法。
一般的想法是在提交表单后将用户重定向到其他页面,这将在页面刷新时停止重新提交表单。不过,如果您需要在提交表单后将用户保留在同一页面上,则可以通过多种方式进行操作,但是这里我将描述javascript方法。
JavaScript方法
此方法非常简单,一旦提交表单,就会阻止弹出窗口在刷新时要求重新提交表单。只需将这行javascript代码放在文件的页脚处,然后看一下魔术。
<script>
if ( window.history.replaceState ) {
window.history.replaceState( null, null, window.location.href );
}
</script>
答案 20 :(得分:0)
对我有用的是:
<form action="?refresh=<?php echo createToken(3)?>">
</form>
在您的表单中
{{1}}
答案 21 :(得分:0)
此form.php
示例展示了如何正确使用PRG(无论表单是否有效)。
<?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>
答案 22 :(得分:-1)
if (($_SERVER['REQUEST_METHOD'] == 'POST') and (isset($_SESSION['uniq']))){
if($everything_fine){
unset($_SESSION['uniq']);
}
}
else{
$_SESSION['uniq'] = uniqid();
}
答案 23 :(得分:-2)
为什么不直接使用$_POST['submit']
变量作为逻辑语句来保存表单中的内容。您始终可以重定向到同一页面(如果他们刷新,当他们在浏览器中点击go back
时,将不再设置提交帖子变量。只需确保您的提交按钮有{{1}和name
的{{1}}。