【发布时间】:2016-03-17 07:50:04
【问题描述】:
我花了几个月的时间在我的域上开发一个应用程序。这总体上是一个简单的概念。在开发过程中,我将其托管在自己的域中,但最近将其推送到我们的实际域中。问题是没有在页面之间创建或保留会话,我一生都无法弄清楚原因。
为下面的代码墙道歉,但我更喜欢它而不是理论解释。
让我们从我如何在每一页的顶部开始我的会话:
function sec_session_start() {
$session_name = 'login';
$secure = false;
$httponly = true;
ini_set('session.use_only_cookies', 1);
session_set_cookie_params(86400, '/', '.domain.com', $secure, $httponly);
session_name($session_name);
session_start();
session_regenerate_id();
}
然后我如何检查用户是否已登录。我添加了return x; 而不是false 进行调试。我将此附加到重定向 URL。
function login_check($mysqli) {
if(isset($_SESSION['id'], $_SESSION['login_string'], $_SESSION['type'])) {
$id = $_SESSION['id'];
$login_string = $_SESSION['login_string'];
$user_browser = $_SERVER['HTTP_USER_AGENT'];
if($_SESSION['type'] == 1 || $_SESSION['type'] == 2) // Admin user
{
if ($stmt = $mysqli->prepare("SELECT `password` FROM `users` WHERE `id` = ? LIMIT 1")) {
$stmt->bind_param('s', $id);
$stmt->execute();
$stmt->store_result();
if($stmt->num_rows == 1) {
$stmt->bind_result($password);
$stmt->fetch();
$login_check = hash('sha512', $password.$user_browser);
if($login_check == $login_string) {
return true;
} else {
return 1;
}
} else {
return 2;
}
} else {
return 3;
}
} else if($_SESSION['type'] == 3) { // Standard user
if($stmt=$mysqli->prepare("SELECT `password` FROM `proj` WHERE `id` = ? LIMIT 1"))
{
$stmt->bind_param("s", $_SESSION['id']);
$stmt->execute();
$stmt->store_result();
if($stmt->num_rows == 1)
{
$stmt->bind_result($db_key);
$stmt->fetch();
$login_check = hash('sha512', $db_key.$user_browser);
if($login_check == $login_string) {
return true;
} else {
return 4;
}
}
}
} else {
return 5;
}
} else {
return 6;
}
}
我有两个登录页面,一个用于管理员,一个用于用户。
管理员:
<?php
ini_set('display_errors','On');
error_reporting(E_ALL);
include_once "../functions.php";
include_once "../db_connect.php";
sec_session_start();
if(login_check($mysqli) === true) {
header('Location: ../index.php');
}
else
{
// Login form
}
用户:
<?php
ini_set('display_errors','On');
error_reporting(E_ALL);
include_once "../functions.php";
include_once "../db_connect.php";
sec_session_start();
if(login_check($mysqli) === true) {
header('Location: ../index.php');
}
else
{
// Login form
}
完全一样,除了文件来源,因为管理员login.php 位于/admin。尽管如此,第一个正确显示登录表单,而第二个将您重定向到index.php(即使在隐身状态下,对我来说也是个谜),导致重定向循环(因为index.php 将其发回以让 nog 登录) .
除此之外,当我使用正确的凭据登录时,它确实将我定向到 index.php,只是将我重定向回 login.php,错误代码为 6。
如果您想了解更多信息或代码示例,请发表评论,我现在迷失在自己的项目中。
任何帮助表示赞赏, 谢谢
12 月 17 日更新:
经过几个小时的调试,我们得出结论,问题不在于代码,而在于服务器配置。一个简单的例子:
<?php
session_start();
echo session_id();
?>
如果您在生产服务器上打开此文件并刷新页面,它会在每个请求中显示一个新的会话 ID。我目前不知道为什么。我已经确认创建了会话文件以及 cookie。它包含正确的信息,并且可以通过具有服务器权限的 SSH 访问。确实有些奇怪的行为。
有什么线索吗?
【问题讨论】:
-
确保每个请求只启动一次会话,例如,如果多个文件在同一个请求中调用
sec_session_start(),会发生什么? -
不同的服务器配置会以不同的方式处理会话,例如通过 cookie 或文件等。所以会话的初始化方式会有所不同,这些只是需要考虑的一般 cmets
-
1) 您是否在不同的服务器上设置了本地
php.ini?session.savepath等设置具有帐户特定地址,这些地址将在您的测试和生产服务器上更改。 2) 你的两台服务器是否安装了相同的 PHP 版本? 3)运行phpinfo,比较两台服务器上的输出设置,比较差异(如会话相关地址)。这些有没有给你任何好奇的答案? -
您存储会话的服务器地址是否已正确设置和启用?如具有正确的权限,并且该文件夹存在等?这些都是目前我正在运行的简单试错调试
-
感谢您的 cmets。 1)我在我的问题中没有提到的是它托管在一个子域上,如果有任何兴趣的话。在主域上托管了一个 WordPress,它运行良好。这会以某种方式影响会话路径吗? 2) 是的,或者非常相似。 3)我会试试这个并寻找差异!关于会话路径,我首先使用
session_get_cookie_params()并将其用作保存路径和域。现在的情况只是我第一次尝试解决问题的结果。