且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

PHP 会话:如何编辑其他用户的会话/编辑会话文件

更新时间:2023-12-02 11:40:28

可以修改另一个用户会话(见下文),尽管我个人建议不要这样做.正如我想象的那样,它可以打开一个充满会话劫持和其他漏洞的世界.

以您的示例用例

一个普通用户被登录,同时管理员使用管理功能并为此用户更改一些值.如果该值不是每次都从数据库中获取的值,则需要更改当前登录用户的会话变量的值.

您***更新数据库中的值,然后在处理下一页之前检查它是否已更改.如果您不想在每个页面加载之前检查多个用户字段,那么当您在管理面板中更新用户时,您可以构建值的哈希并将其添加到名为 session_hash 的新列中.然后在页面加载时比较这个字段

但如果您仍想修改其他用户的会话,您可以将您当前的 session_id 设置为目标.

//结束我当前的会话并保存它的 idsession_start();$my_session_id = session_id();session_write_close();//修改我们的目标会话session_id($target_id);session_start();$_SESSION['is_logged_in'] = false;session_write_close();//再次开始我们的旧会话session_id($my_session_id);session_start();

编辑

示例:https://www.samdjames.uk/session_example/index.php一个>

示例源:https://gist.github.com/SamJUK/c220e3742632f5/p>

EDIT - 2: See Sam's solution for the case. The old methods i'll still leave here as well as the problem itself, but a new solution was build based on Sam's solution, and it is available in the repository at github on the project i keep

EDIT - 1: SEE THE METHOD destroy(id) for a workaround

Currently I have the need in some occasions in my System that requires other users session to be update with a new value. The current case now needs a single value to be changed in the session file of some users when a certain action is performed. In my project i have created a class SessionHandlerCustom that implements the SessionHandlerInterface, and with that I have implemented a logic that creates a Custom session with an Id for each user. I can access the file in a custom directory, but strangely I can't use file_put_contents or file_get_contents to these Session files. I tried to work around with Session functions, and by using the read() function presented in the SessionHandlerCustom i was able to get all the contents from a user's session using it's SessionId.

The method working, SessionFileGetValueByHashCode, is the one that gets the content from a Session, and with some Key (usually the field name i want in the file), it will get the exactly string of that key with it's values. The second method, not working at all, is the one that will actually change the value in the Session, but it just doesn't. I have tried manipulating the file directly with no success and have tried to use the SessionHandlerCustom->write() method but it has no effect.

Could anyone help me out and explain how is the correct way to change/manipulate the session of other user's ?

A System example: A common user is logged, while in the same time an administrator uses the Admin functions and change some value for this user. If the value is not something obtained from the database every time, the session variable for that current logged in user need to have its value changed.

If you get curious, the System is Open Source, and you can access it here: https://github.com/msiqueira-dev/InfraTools

\*
This should be in the class that implements SessionHandlerInterface. This will actually delete the users session and force it to reload the whole session when it makes another request. The $SavePath variable is variable create and stored with the directory folder of the Session.
*/
public function destroy($id)
    {
        $file = $this->SavePath . "/sess_" . $id;
        if (file_exists($file)) 
            unlink($file);
        return true;
    }

SessionFileGetValueByHashCode

//The &$Value will be filled with the whole $Key and its values presented in the Session File. For example: SomeValue|s:0:"";
public function SessionFileGetValueByHashCode(&$Value, $Application, $SessionId, $Key)
{
        $Value = NULL;
        if(isset($Application) && !empty($Application) && isset($SessionId) && !empty($SessionId) && isset($Key) && !empty($Key))
        {
            $file = SESSION_PATH . $Application . "/sess_" . $SessionId;
            if(file_exists(($file)))
            {
                $str = $this->InstanceSessionHandlerCustom->read($SessionId);
                $start = strpos($str, $Key);
                $end=$start;
                while($str[$end] != '"')
                {
                    $Value .= $str[$end];
                    $end++;
                }
                $Value .= '"';
                $end++;
                while($str[$end] != '"')
                {
                    $Value .= $str[$end];
                    $end++;
                }
                $Value .= '"';
                if($Value != NULL)
                    return Config::RET_OK;
            }
        }
        return Config::RET_ERROR;
    }

SessionFileUpdateValueByHashCode

public function SessionFileUpdateValueByHashCode($Application, $SessionId, $OldValue, $NewValue)
    {
        if(isset($Application) && !empty($Application) && isset($SessionId) && !empty($SessionId) 
                               && isset($OldValue) && !empty($OldValue) && isset($NewValue) && !empty($NewValue))
        {
            $file = SESSION_PATH . $Application . "/sess_" . $SessionId;
            if(file_exists(($file)))
            {
                $str = $this->InstanceSessionHandlerCustom->read($SessionId);
                $str = str_replace($OldValue, $NewValue, $str, $count);
                if($count > 0)
                {
                    echo $str . "<br>";
                    if($this->InstanceSessionHandlerCustom->write($SessionId, $str))
                        return Config::RET_OK;
                }
            }
        }
        return Config::RET_ERROR;
    }

You can modify another users session (see below), although personally, I would recommend against it. As I imagine it can open up a whole world of session hijacking and other vulnerabilities.

With your example use case

A common user is logged, while in the same time an administrator uses the Admin functions and change some value for this user. If the value is not something obtained from the database every time, the session variable for that current logged in user need to have its value changed.

You would be better of updating the value in the database and then just checking to see if it's changed before you process the next page. If you don't want to be checking multiple user fields before each page load then when you update the user in the admin panel, you can build a hash of the values and add it to a new column called session_hash. Then just compare this field on page load

But if you still want to modify another user's session, you can set your current session_id to the targets.

// End my current session and save its id
session_start();
$my_session_id = session_id();
session_write_close();

// Modify our target session 
session_id($target_id);
session_start();
$_SESSION['is_logged_in'] = false;
session_write_close();

// Start our old session again
session_id($my_session_id);
session_start();

EDIT

Example: https://www.samdjames.uk/session_example/index.php

Example Src: https://gist.github.com/SamJUK/c220e3742487567c6262238edf85695e