【问题标题】:session variables disappear?会话变量消失?
【发布时间】:2015-02-23 17:04:39
【问题描述】:

我正在尝试了解有关密码哈希和安全登录等的更多信息,因此我尝试在此处复制 this 示例。我没有 100% 重复这个。

我遇到的问题是,当我输入登录凭据时,表单会转到验证密码等的process_login.php 脚本,并设置$_SESSION 变量。成功后,它应该重定向到protected.php,这是一个只有在用户登录时才能访问的站点。

对我来说,它不起作用仅仅是因为 $_SESSION 变量消失了!

我正处于process_login.php 脚​​本显示$_SESSION 已设置的位置,然后我使用header("Location: protected.php");,它告诉我$_SESSION 数组为空。这怎么可能?我错过了这里的船......

以下是相关的代码部分:

process_login.php

process_login.php

include_once 'connect.php';
include_once 'functions.php';
sec_session_start();

if (isset($_POST['eml'], $_POST['h'])) {
    $email = $_POST['eml'];
    $pwd_hash = $_POST['h'];
    if (login($email, $pwd_hash, $mysqli) == true) {
        // in my situation, this returns true
        // and the redirect to "protected.php" happens
        header('Location: protected.php');
    } else {
        header("Location: error?err=Wrong password");
    }
} else {
    exit('Invalid Request');
}

login() 函数

function login($email, $password, $mysqli) {
    if ($stmt = $mysqli->prepare("SELECT id, email, pwd, salt FROM public WHERE email=? LIMIT 1")) {
        $stmt->bind_param('s', $email);
        $stmt->execute();
        $stmt->store_result();
        $stmt->bind_result($user_id, $email, $db_password, $salt);
        $stmt->fetch();
        $password = crypt($password, $salt);
        if ($stmt->num_rows == 1) {
            if (checkbrute($user_id, $mysqli) == true) {
                // Account is locked 
                $status = "3";
                $mysqli->query("INSERT INTO login_activity(user, status, ip)
                                VALUES ('$email', '$status', '{$_SERVER['REMOTE_ADDR']}')");
                sleep(8);
                header("Location: ../error?err=The account you try to access is currently blocked.");
                return false;
            } else {
                // Check if the password in the database matches
                // the password the user submitted.
                if ($db_password == $password) {
                    // Password is correct!
                    // Get the user-agent string of the user.
                    $user_browser = $_SERVER['HTTP_USER_AGENT'];
                    // XSS protection as we might print this value
                    $user_id = preg_replace("/[^0-9]+/", "", $user_id);
                    $_SESSION['user_id'] = $user_id;
                    $_SESSION['login_string'] = hash('sha512', $password . $user_browser);
                    $status = "1";
                    $mysqli->query("INSERT INTO login_activity (user, status, ip)
                                    VALUES ('{$_SESSION['user_id']}', '$status', '{$_SERVER['REMOTE_ADDR']}')");
                    return true;
                } else {
                    // Password is not correct
                    // We record this attempt in the database
                    $status = "2";
                    $mysqli->query("INSERT INTO login_activity(user, status, ip)
                                    VALUES ('$email', '$status', '{$_SERVER['REMOTE_ADDR']}')");
                    sleep(3);
                    header("Location: ../error?err=Password is not correct.");
                    return false;
                }
            }
        } else {
            // No user exists.
            sleep(2);
            header("Location: ../error?err=No user exists.");
            return false;
        }
        header("Location: ../error?err=You can't see this.");
        return false;
    } else {
        header("Location: ../error?err=DB fail: ".$mysqli->error);
        return false;
    }
}

protected.php

protected.php

<?php
include_once 'connect.php';
include_once 'functions.php';
sec_session_start();
// $return = login_check($mysqli);
print_r(get_defined_vars());
// this outputs an empty $_SESSION array
exit;

函数 sec_session_start()

function sec_session_start() {
    $session_name = 'sec_session_id';
    $secure = true;
    $httponly = true;
    if (ini_set('session.use_only_cookies', 1) === FALSE) {
        header("Location: ../error?err=Could not initiate a safe session (ini_set)");
        exit();
    }
    $cookieParams = session_get_cookie_params();
    session_set_cookie_params($cookieParams["lifetime"],
        $cookieParams["path"], 
        $cookieParams["domain"], 
        $secure,
        $httponly);
    session_name($session_name);
    session_start();
    session_regenerate_id();
}

我试图看看如果我只是使用sec_session_start() 开始会话会发生什么,结果如下:

include_once 'connect.php';
include_once 'functions.php';
sec_session_start();
$_SESSION["test"] = "works!";
header('Location: protected.php');

print_r(get_defined_vars());protected.php 中的输出是:

[_SESSION] => Array ( )

【问题讨论】:

  • 什么是sec_session_start()
  • @Stony 我现在将此功能添加到我的问题中。
  • 你为什么要睡觉?为什么盐在数据库中?使用 password_hash 和 password_verify
  • @RonniSkansing sleep() 作为针对暴力攻击的额外措施。根据我正在使用的网站的示例,Salt 在数据库中。不确定是否有更好的方法来做到这一点。不知道你还提到了什么。这跟我的问题有关系吗?
  • 我认为问题在于其中一项设置不允许写入会话。我会在 php 上仔细检查这个函数,看看它是如何应用于你的环境的。 php.net/manual/en/function.session-set-cookie-params.php

标签: php security session session-variables password-encryption


【解决方案1】:

这可能对许多会话问题有所帮助。我已经使用 PHP 很多年并且喜欢它, 但它很古怪!

在这段代码中 -

page1.php

<?phpsession_start();?>

<?php
$_SESSION['roman']="kitty";
echo ('<a href="page2.php"> Go To Page 2</a>');
?>

page2.php

<?php session_start();?>

<?php
echo $_SESSION['roman'];
?>

注意第 1 页的 'phpsession_start()' 中没有空格, 但我确实在 page2 的 'php session_start()' 中使用了一个空格。

在 page2 中使用 NO 空间,并且会话变量消失了。有一个空间它工作正常。 在 page1 中,不管有没有空格都可以。我有其他脚本在哪里 这是相反的。只会在没有空间的情况下工作!尝试检查的东西也是如此。

现在很多人可能会粘贴此代码并让它工作,或者不像我描述的那样工作,但这就是为什么 这很古怪!

【讨论】:

    猜你喜欢
    • 2012-09-02
    • 2014-02-15
    • 1970-01-01
    • 2012-12-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多