Php 防止在手动页面刷新时插入重复记录
我有一个问题刚刚浮出水面 我在MVC环境中工作。我的接口类中的方法名称与请求模块和操作的名称相匹配,即模块=test&action=action将产生一个名为Php 防止在手动页面刷新时插入重复记录,php,refresh,Php,Refresh,我有一个问题刚刚浮出水面 我在MVC环境中工作。我的接口类中的方法名称与请求模块和操作的名称相匹配,即模块=test&action=action将产生一个名为public function test_action(){} 在这个特殊的问题中,我有一个表单,它会自动提交。如果验证通过,将创建一条记录,然后显示另一个模块的模板。此模块需要一系列post变量,因为它在两个模块中使用 我遇到的问题是,如果用户成功通过验证并尝试F5页面,就会创建另一条新记录,等等 我怎样才能防止这种情况发生 正常情况下,
public function test_action(){}
在这个特殊的问题中,我有一个表单,它会自动提交。如果验证通过,将创建一条记录,然后显示另一个模块的模板。此模块需要一系列post变量,因为它在两个模块中使用
我遇到的问题是,如果用户成功通过验证并尝试F5页面,就会创建另一条新记录,等等
我怎样才能防止这种情况发生
正常情况下,我会在成功插入后重定向页眉,但在本例中我不能。成功插入后,您可以/应该重新定向到新页面
当您在MVC中工作时,您可以添加一个新的控制器,该控制器只调用要显示的视图。开发人员错误: 您需要创建一个处理程序页面,其中:
- 验证发送的数据
- 插入行
- 重定向用户
您在这样做时是否遇到了一些错误?如果出于任何原因无法重定向(听起来很奇怪),您可以使用“相同” 用于数据验证的机制,用于在成功插入后刷新表单
但这真是一种丑陋的方式。我会采取完全不同的方式。我甚至发现重定向是一种不正确的处理方法,因为更改位置并不意味着克服逻辑/表单问题 正确的解决方案是:
- 在隐藏输入中向窗体添加唯一的哈希
- 将哈希存储在服务器端会话中
- 发送表单时,使用服务器上的哈希验证隐藏的输入哈希
- 仅在表单正确验证时执行行插入
如果您使用的是Zend Framework,那么有一个
Zend\u Form\u Element\u Hash
类供您使用。以下是我所做的。这对我有用。希望它能帮助其他人
//+++ start token +++
//This is to prevent duplicate entry on page reload (F5). 19. If I enter all values, press Record in journal and then press F5, the same values are recorded one more time. Need to prevent
// 3rd. $token_hash_from_input get value of input field name name="' .$_SESSION['token_hash'] .'"
$token_hash_from_input = $_SESSION['token_hash'];
//echo $token_hash_from_input .' token_hash_from_input<br>';
//echo $_POST[$token_hash_from_input] .' $_POST[$token_hash_from_input]<br>';
//var_dump($token_hash, $_POST);
// 4th. $_SESSION['token'] created/set in 1st. Then it as if goes around (at first to input field then after page reload returns here). However $_POST[$token_hash_from_input] is value received directly from input field. User click post and input field value is passed to $_POST[$token_hash_from_input]. Here I compare both.
if ( $_SESSION['token'] != htmlspecialchars($_POST[$token_hash_from_input]) ) {
$token_error .= 'yes';
//echo 'session token and token from input field are not the same <br> ';
}
else {
//echo 'session token is equal to post$token_hash)<br>';
}
// 1st. Create token and pass it to session
$token = sha1(uniqid(mt_rand(), true));
$_SESSION['token'] = $token;
//echo $_SESSION['token'] .' new $_SESSION[token]<br>';//after each page reload new token created. Then this token passed to input form (hidden field). value="' .$_SESSION['token'] .'"
// 2nd. Create token_hash and pass it to session. Token hash is to name input fields name and id. I may not use $token_hash and $_SESSION['token_hash']. Instead of this I can use name="token" and id="token".
$token_hash = sha1(uniqid($time_when_form_submitted .'token' .$_SERVER["REMOTE_ADDR"]));
//echo $token_hash .' $token_hash<br>';
$_SESSION['token_hash'] = $token_hash;
//echo $_SESSION['token_hash'] .' new SESSION$token_hash<br>';
// +++ end token +++
/+/+++启动令牌+++
//这是为了防止页面重新加载(F5)时出现重复条目。19如果我输入所有值,按Record in journal,然后按F5,相同的值将再次记录。需要预防
//三,$令牌\u散列\u从\u输入获取输入字段名称的值=“”。$\u会话['令牌\u散列']”
$token\u hash\u from\u input=$\u SESSION['token\u hash'];
//从输入回显$token\u hash\u。“从输入回显$token\u hash\u
”;
//echo$\u POST[$token\u hash\u from\u input].$\u POST[$token\u hash\u from\u input]
;
//var\u dump($token\u hash,$\u POST);
//第四$_会话['token']在第1个会话中创建/设置。然后,它就好像在四处走动(首先是输入字段,然后在页面重新加载后返回这里)。但是$\u POST[$token\u hash\u from\u input]是直接从输入字段接收的值。用户单击post并将输入字段值传递给$\u post[$token\u hash\u from\u input]。在这里我比较两者。
if($\u SESSION['token']!=htmlspecialchars($\u POST[$token\u hash\u from\u input])){
$token_错误='yes';
//echo“会话令牌和来自输入字段的令牌不相同
”;
}
否则{
//echo“会话令牌等于post$token_hash)
”;
}
//第一。创建令牌并将其传递给会话
$token=sha1(uniqid(mt_rand(),true));
$\会话['token']=$token;
//echo$_会话['token'.'新的$_会话[token]
//在每个页面之后,重新加载创建的新令牌。然后这个令牌被传递到输入表单(隐藏字段)。value=“.$”会话['token']”
//第二。创建令牌\u散列并将其传递给会话。令牌散列用于命名输入字段名称和id。我不能使用$Token\u散列和$u会话['Token\u散列']。我可以使用name=“token”和id=“token”来代替它。
$token_hash=sha1(uniqid($time_when__form_submitted.'token'.$_SERVER[“REMOTE_ADDR”]);
//回显$token_散列。“$token_散列
”;
$\u会话['token\u hash']=$token\u hash;
//echo$会话['token\u hash'.'新会话$token\u hash
';
//+++结束标记+++
像这样的输入字段
<input type="hidden" name="' .$_SESSION['token_hash'] .'" id="' .$_SESSION['token_hash'] .'" value="' .$_SESSION['token'] .'">
或
许多web开发人员在其web应用程序中面临的最常见问题之一是在页面刷新时将重复记录插入数据库。如果网页包含一些文本框和将文本框数据提交到数据库的按钮。在这种情况下,当用户向文本框中插入一些数据并单击“提交”按钮时,它会将记录保存到数据库中,然后如果用户立即刷新网页,则相同的记录会再次保存到数据库中,因为没有可用于验证数据存在性的唯一键,以防止多次插入
从这个行为我们可以明确地知道,在页面刷新时,按钮单击事件被触发。
为了避免这个问题,我们可以尝试下面讨论的方法
在页面加载事件中,将日期/时间戳保存在会话变量中,当首次加载页面时,将使用当前日期/时间填充会话变量,如下所示:
void Page_PreRender(object obj,EventArgs e)
{
ViewState["update"] = Session["update"];
}
*无效页面加载(对象发送方,事件参数e)
{
如果(!IsPostBack)
{
会话[“更新”]=Server.UrlEncode(System.DateTime.Now.ToString());
}
}*
在页面的PreRender事件中,ViewState变量设置为会话变量的值,如下所示:
void Page_PreRender(object obj,EventArgs e)
{
ViewState["update"] = Session["update"];
}
然后,在运行数据库插入命令之前,将这两个值相互比较。
如果它们相等,则允许执行该命令,并使用当前日期/时间更新会话变量,否则将忽略该命令,如下所示:
void btnSubmit_Click(object obj, EventArgs e)
{
string name = "";
string qualification = "";
if (Session["update"].ToString() == ViewState["update"].ToString())
{
if (txtName.Text != "" || txtName.Text != null)
{
name = txtName.Text.ToString();
}
if (txtQualification.Text != "" || txtQualification.Text != null)
{
qualification = txtQualification.Text.ToString();
}
//--- Insert data function should be execute here
string strSql = "INSERT INTO Testdata (Name,Qualification) VALUES ('" + name + "','" + qualification + "')";
SqlConnection ANConnection = new SqlConnection(ConnectionString);
ANConnection.Open();
SqlCommand ANCommand = new SqlCommand(strSql, ANConnection);
ANCommand.ExecuteNonQuery();
ANConnection.Close();
ANConnection.Dispose();
//--End of save data
lblMessage.Text = "Inserted Record Sucessfully
Session["update"] = Server.UrlEncode(System.DateTime.Now.ToString());
}
else
{
lblMessage.Text = "Failure – Due to Page Refresh";
txtName.Text = "";
txtQualification.Text = "";
}
}
这是一个问题。通常问题都放在评论中。删除重复的内容,因为他声明他不能重定向。我想说,如果没有重定向,这或多或少是不可能的。