PHP 会话在页面之间丢失 - 行为因服务器而异 [英] PHP sessions lost between pages - behaves differently depending on server

查看:67
本文介绍了PHP 会话在页面之间丢失 - 行为因服务器而异的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我花了几个月的时间在我的领域开发应用程序.总的来说,这是一个简单的概念.在开发过程中,我自己将它托管在我自己的域中,但最近将它推到了我们的实际域中.问题是会话不是在页面之间创建或保持的,我一生都无法弄清楚原因.

I have spent a couple of months developing an application on a domain of mine. It's overall a simple concept. During development I hosted it myself on my own domain, but recently pushed it to our actual one. The problem is that sessions aren't created or kept between pages, and I can't for the life of me figure out why.

为下面的代码墙道歉,但我更喜欢它而不是理论上的解释.

Apologize for the wall of code below, but I prefer it over a theoretical explanation.

让我们从如何在每个页面的顶部开始我的会话开始:

Lets start with how I start my session at the top of every page:

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.

And then how I check if the user is logged in. I added return x; instead of false for debugging. I append this to the redirect 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;
}
}

我有两个登录页面,一个给管理员,一个给用户.

I have two login pages, one for admins and one for users.

管理员:

<?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 ).php 在 nog 登录时将其发送回来).

Quite identical, apart from the file sources as the admin login.php is located in /admin. Despite this, the first one displays the login form correctly while the second redirects you to index.php (even when in incognito, a mystery to me), causing a redirect loop (as index.php sends it back for nog being logged in).

除此之外,当我使用正确的凭据登录时,它确实将我定向到 index.php 只是将我重定向回 login.php 并带有错误代码 <代码>6.

In addition to this, when I login with proper credentials, it does direct me to index.php only to redirect me back to login.php with error code 6.

如果您需要更多信息或代码示例,请发表评论,我现在对自己的项目感到迷失.

Please do comment if you want more information or code examples, I feel lost in my own project right now.

感谢任何帮助,谢谢

12 月 17 日更新:

经过几个小时的调试,我们得出结论,问题不在于代码,而在于服务器配置.一个简单的例子:

After a few hours of debug, we've concluded that the issue is not with the code but with the server configuration. A simple example:

<?php

session_start();
echo session_id();

?>

如果您在生产服务器上打开此文件并刷新页面,它会在每个请求中显示一个新的会话 ID.我目前不知道为什么.我已经确认会话文件和 cookie 都已创建.它包含正确的信息,可以通过具有服务器权限的 SSH 访问.真是一些奇怪的行为.

If you open this file on the production server, and refresh the page, it displays a new session id with every request. I currently have no clue why. I have confirmed the session file is created as well as the cookie. It contains the proper information and can be accessed by SSH with server permissions. Truly some strange behavior.

有什么线索吗?

推荐答案

我已经检查了你的代码,除了只有 1 件事外,我没有发现任何异常.

I have gone through your code and I didn't find any thing unusal except only 1 thing.

你永远不应该使用 == 进行字符串比较 === 是可以的.

You should never use == for string comparison === is OK.

$something = 0;
echo ('password123' == $something) ? 'true' : 'false';

运行上面的代码,你会发现你的会话丢失的原因.在您的函数 login_check 中,您使用 == 来比较两个字符串

Run the above code and you will find the reason of your session lost. In your function login_check you are using == for comparing two string

 if($login_check == $login_string)

替换为:

 if($login_check === $login_string)

其他一切都绝对没问题.如果更改这件小事不能解决您的问题,请告诉我.

Else every thing is absolutly fine. If changing this little thing doesn't resolve your problem then just let me know.

您正在会话开始前连接到数据库.我建议您导入您的函数,然后启动您的会话,然后连接到您的数据库.

You are connecting to DB before session start. I would recommend you to import your function then start your session and then connect to your database.

include_once "../functions.php";
sec_session_start();
include_once "../db_connect.php"; 

这篇关于PHP 会话在页面之间丢失 - 行为因服务器而异的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆