我试图尽可能具体,但我很抱歉我的问题的主题可能很广泛。
我习惯于使用$ _GET ['variable']发送变量,例如,假设我使用ajax从数据库中获取一些信息,我可能会这样做:
xmlhttp.open("GET","read.php?option=someoption",true);
然后我会根据它会收到的$_GET['option']
以不同的方式设置PHP页面。
然后我意识到任何登录用户都可以输入URL并直接修改数据库,所以我在每次重定向之前设置了一些额外的$_SESSION['redirect']
变量,以帮助防止访问php页面URL。通过对“prevent.php”页面进行快速ajax调用,可以执行类似的操作:
$_SESSION['redirect'] = "true";
header("Location: page.php");
然后让它在page.php中以这种方式设置,例如:
if ($_SESSION['redirect']==true) {
// access the database
}
else {
// deny access
}
这是一种可靠的做事方式,还是有更专业的方法来解决问题?
答案 0 :(得分:0)
不,这不是一种安全的做法。
以下是您如何以最简单的形式实现安全用户系统的示例:
的login.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>';
}
管理员-page.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.';
}
用户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:
的侵害例如,记录用户的不安全方式是:
logout.php:
<?php
session_start();
if (isset($_SESSION['user'])) {
session_destroy();
}
也许你会问自己为什么这不安全。
原因是因为每个用户的注销链接都是相同的(example.com/logout.php
)。
因此,猜测退出链接并不难(嗯,我们甚至不必猜测,我们已经确定了)。
攻击者可以伪装注销链接,一旦点击它就会被注销。
了解退出只是一个例子非常重要。
考虑更严厉的行为,例如删除用户等。
因此,此概念适用于经过身份验证的用户可以执行的每项操作。
为安全起见,您可以在用户登录后立即生成令牌。
对于您执行的每个操作,请检查请求中的令牌是否与您生成的令牌匹配。
这样,注销链接对于每个用户(example.com/loogut.php?token=random_token_generated_at_login
)都是唯一的,并且攻击者很难猜到。
安全-logout.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
}
}
否: POST 请求与 GET 请求一样容易受到影响。
因此,无论使用何种HTTP方法,请确保检查每个操作的令牌。