不,这不是一种安全的方式。
以下是如何以最简单的形式实现安全用户系统的示例:
登录.php
<?php
session_start();
$user = isset($_POST['username']) ? $_POST['username'] : false;
$pass = isset($_POST['password']) ? $_POST['password'] : false;
# Check credentials
if (validCredentials($user, $pass)) {
# Credentials are valid
# Set isAdmin session for the user 'admin'
# This is hardcoded for simplicity but
# you could read a value from a database
# and set this session dynamically.
if ($user === 'admin') {
$_SESSION['isAdmin'] = true;
}
# Generate CSRF token (see appendix)
# heads up: random_bytes() is a PHP7 function.
$_SESSION['token'] = bin2hex(random_bytes(32));
# Set logged in session for every user
$_SESSION['user'] = $user;
echo 'Successfully logged in!<br />';
echo '<a href="user-page.php">Go to the user page.</a>';
}
管理页面.php:
<?php
session_start();
if (isset($_SESSION['isAdmin']) && $_SESSION['isAdmin'] === true) {
echo 'Only the admin can see this.';
} else {
echo 'You are either not logged in or you don\'t have the permission to view this page.';
}
用户页面.php:
<?php
session_start();
if (isset($_SESSION['user'])) {
$token = $_SESSION['token'];
echo 'Only logged in users can see this. <br />';
echo '<a href="safe-logout.php?token='.$token.'">Log me out</a>.';
} else {
echo 'You are not logged in.';
}
附录:
确保您保护自己免受CSRF attacks:
例如,一种不安全的用户注销方式是:
注销.php:
<?php
session_start();
if (isset($_SESSION['user'])) {
session_destroy();
}
也许您会问自己为什么这不安全。
原因是每个用户的注销链接都是相同的 (example.com/logout.php)。
所以猜测注销链接一点也不难(好吧,我们甚至不必猜测,我们已经确定了)。
攻击者可以伪装注销链接,一旦您单击它,您就会被注销。
了解注销只是一个示例,这一点非常重要。
考虑更严重的操作,例如删除用户等。
所以这个概念适用于经过身份验证的用户可以执行的每个操作。
为安全起见,您可以在用户登录后立即生成令牌。
对于所采取的每一项操作,然后检查请求中的令牌是否与您生成的令牌匹配。
这样,每个用户 (example.com/loogut.php?token=random_token_generated_at_login) 的注销链接都是唯一的,攻击者很难猜到。
安全注销.php:
<?php
session_start();
if (isset($_SESSION['user'])) {
# Check if the user specified token matches ours
$token = isset($_GET['token']) ? $_GET['token'] : false;
if ($_SESSION['token'] === $token) {
session_destroy();
echo 'Successfully logged out!';
} else {
# We dont logout because the token was not valid
}
}
NO:POST 请求与 GET 请求一样容易受到影响。
因此,无论使用哪种 HTTP 方法,请务必检查每个操作的令牌。