PHP - $ _SESSION []是保护php内容的可靠方法吗?

时间:2017-08-26 16:12:49

标签: php

我试图尽可能具体,但我很抱歉我的问题的主题可能很广泛。

我习惯于使用$ _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
} 

这是一种可靠的做事方式,还是有更专业的方法来解决问题?

1 个答案:

答案 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方法,请确保检查每个操作的令牌。