【发布时间】: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