【发布时间】:2015-05-22 17:45:26
【问题描述】:
我有一个表格,我希望它尽可能安全。所以我有这个生成表单令牌的函数。
function generateFormToken($form) {
// generate a token from an unique value
$token = hash('sha256', uniqid(microtime()));
// Write the generated token to the session variable to check it against the hidden field when the form is sent
$_SESSION[$form.'_token'] = (string)$token;
return $token;
}
以下是它的激活方式:
if (empty($_POST)){
$newToken = generateFormToken('form1');
}
这是我用来检查的函数:
function verifyFormToken($form) {
// check if a session is started and a token is transmitted, if not return an error
if(!isset($_SESSION[$form.'_token'])) {
return false;
}
// check if the form is sent with token in it
if(!isset($_POST['token'])) {
return false;
}
// compare the tokens against each other if they are still the same
if ($_SESSION[$form.'_token'] !== $_POST['token']) {
return false;
}
return true;
}
我的 HTML 表单有一个隐藏的输入,我在其中放置了新的令牌变量。该表格正在通过form action="#" 发送到同一页面。
我遇到的问题是,由于某种原因,当页面刷新时,即使函数没有再次调用,令牌在会话中也会发生变化,但在表单中保持不变。
我真的很迷茫,因为我认为要求 PHP 在会话中存储一个字符串在这些条件下刷新页面时它不会改变,但它总是给我不同的响应。我试图在它进入函数之前调用die(),以确保该函数没有以某种方式再次加载到脚本中的更远位置,但没有任何反应。理论上应该不会刷新。
请帮帮我。
这是 HTML 表单:
<form action="#" method="POST" id="form1">
<label for="firstname">Firstname</label>
<input type="text" name="firstname">
<input type="hidden"name="token" value="<?= $newToken; ?>">
</form>
这是我在页面顶部使用的验证逻辑:
$msg = "";
//If the form has been filled
if (!empty($_POST)){
//If the form has been sent from our website
if (verifyFormToken('form1') == true){
//TODO CAPTCHA
if (1 == 1){
//Everything's fine
}
else{
$msg = 'Veuillez cocher la case «Je ne suis pas un robot».';
}
}
//Else, user tried to send data with his own script (Possible XSS attack)
else{
$msg = 'Veuillez utiliser le formulaire directement sur notre site Web afin d\'appliquer sur l\'offre d\'emploi';
}
}
else{
//If form is not sent, we generate a new token and store it in the user's session
$newToken = generateFormToken('form1');
}
if (!empty($msg)){
echo $msg;
}
【问题讨论】:
-
您确定该函数没有再次运行?您是否尝试过
print_r($_POST)以确保它是空的。尝试在函数内添加echo语句,看看它是否在每次刷新时都被命中。 -
100% 确定...,我试过了,但没有任何回应
-
您的隐藏属性不包含名称属性,并确保在您的服务器上启用短标签
-
如果您发布的不是您的“实际”代码,那么我不喜欢猜测。如前所述,请确保您开始了会话。太多未知数。
-
您说您的“真实”和“实际”代码包含它的名称属性。好吧,这告诉我,你的代码的其他部分可能不是它们应该是的,这是有风险的,我无法测试这个;不是不知道我真正在处理什么。您需要调试您的代码,因为我已经在一开始就已经给了您一些相关的内容。祝你好运。