我写了一个脚本来用会话令牌保护我的表单;但是,如果我在检查令牌之前尝试验证表单字段,则我的脚本不起作用。有人会帮我弄清楚我的剧本有什么问题吗?
<?php
session_start();
class TOKEN {
public static function generate() {
return $_SESSION['token'] = base64_encode(openssl_random_pseudo_bytes(15));
}
public static function check($token) {
if (isset($_SESSION['token']) && $token === $_SESSION['token']) {
unset($_SESSION['token']);
return true;
}
return false;
}
}
?>
<?php
$display_form = FALSE;
if (isset($_POST['submit'])) {
$username = $_POST['username'];
$userpass = $_POST['userpass'];
if (strlen($username) < 4) {
$error_name = 'required';
$display_form = true;
$validation_error = true;
}
if (strlen($userpass) < 8) {
$error_pass = 'required';
$display_form = true;
$validation_error = true;
}
if (!$validation_error) {
if (TOKEN::check($_POST['token'])) {
echo 'process form';
} else {
echo 'invalid security token';
}
}
} else {
$display_form = TRUE;
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<?php
if ($display_form == true) {
?>
<form method="post" action="<?php echo htmlspecialchars($_SERVER['REQUEST_URI']); ?>">
<input type="hidden" name="token" value="<?php echo TOKEN::generate(); ?>">
<input type="text" name="username" id="" placeholder="username">
<?php echo $error_name; ?>
<br>
<input type="password" name="userpass" id="" placeholder="Password">
<?php echo $error_pass; ?>
<br>
<input type="submit" name="submit" value="Sign in">
</form>
</body>
</html>
<?php
}
?>
答案 0 :(得分:0)
这段代码很难阅读。我不知道if语句何时开始和结束。也停止使用所有类的类。像大男孩一样使用程序式编程。
您的问题很简单。 $validation_error
未在外部范围内初始化。这意味着它没有在if语句之间保存。
要解决此问题,只需在外部范围添加$validation_error = false
:
...
$display_form = FALSE;
$validation_error = false; // right here
if (isset($_POST['submit'])) {
$username = $_POST['username'];
$userpass = $_POST['userpass'];
...
答案 1 :(得分:0)
我想这里的问题如下。
因此,无论您在表单中有错误或正确的值,解决方案都是unset
令牌始终。
<强>更新强>
我想它应该是这样的:
if (!$validation_error) {
// here token will be removed in `TOKEN::check`
if (TOKEN::check($_POST['token'])) {
echo 'process form';
} else {
echo 'invalid security token';
}
} else {
// remove token implicitly
TOKEN::remove();
}
在TOKEN
:
public static function check($token) {
$result = false;
if (isset($_SESSION['token'])) {
if ($token === $_SESSION['token']) {
$result = true;
}
// if token set - remove it
self::remove();
}
return $result;
}
public static function remove() {
unset($_SESSION['token']);
}