问题描述
编辑 - 2:请参阅 Sam 的案例解决方案.旧的方法和问题本身我仍然会保留在这里,但是一个新的解决方案是基于 Sam 的解决方案构建的,它可以在我保留的项目的 github 存储库中找到
编辑 - 1:查看方法 destroy(id) 以获取解决方法
目前,我的系统在某些情况下需要使用新值更新其他用户会话.当前案例现在需要在执行某个操作时在某些用户的会话文件中更改单个值.在我的项目中,我创建了一个实现 SessionHandlerInterface 的类 SessionHandlerCustom,并且我已经实现了一个逻辑,为每个用户创建一个带有 Id 的自定义会话.我可以访问自定义目录中的文件,但奇怪的是我不能对这些会话文件使用 file_put_contents 或 file_get_contents .我尝试使用 Session 函数,并且通过使用 SessionHandlerCustom 中提供的 read() 函数,我能够使用它的 SessionId 从用户的会话中获取所有内容.
工作的方法,SessionFileGetValueByHashCode,是从会话中获取内容的方法,并且使用一些键(通常是我想要在文件中的字段名称),它将获得准确的字符串那个带有它的值的键.第二种方法根本不起作用,它实际上会改变 Session 中的值,但它只是没有.我尝试过直接操作文件但没有成功,并尝试使用 SessionHandlerCustom->write() 方法但没有效果.
谁能帮我解释一下更改/操纵其他用户会话的正确方法是什么?
系统示例:登录一个普通用户,同时管理员使用管理功能并更改此用户的某些值.如果该值不是每次都从数据库中获取的值,则需要更改当前登录用户的会话变量的值.
如果您感到好奇,该系统是开源的,您可以在这里访问:https://github.com/msiqueira-dev/InfraTools
\*这应该在实现 SessionHandlerInterface 的类中.这实际上会删除用户会话并强制它在发出另一个请求时重新加载整个会话.$SavePath 变量是变量创建并存储在 Session 的目录文件夹中.*/公共函数销毁($ id){$file = $this->SavePath ."/sess_" .$id;如果(文件存在($文件))取消链接($文件);返回真;}
SessionFileGetValueByHashCode
//&$Value 将填充整个 $Key 及其在会话文件中显示的值.例如: SomeValue|s:0:"";公共函数 SessionFileGetValueByHashCode(&$Value, $Application, $SessionId, $Key){$Value = NULL;if(isset($Application) && !empty($Application) &&isset($SessionId) && !empty($SessionId) &&isset($Key) && !空($Key)){$file = SESSION_PATH .$应用程序."/sess_" .$SessionId;如果(文件存在(($文件))){$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 .= '"';如果($值!= NULL)返回配置::RET_OK;}}返回配置::RET_ERROR;}
SessionFileUpdateValueByHashCode
公共函数 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 .$应用程序."/sess_" .$SessionId;如果(文件存在(($文件))){$str = $this->InstanceSessionHandlerCustom->read($SessionId);$str = str_replace($OldValue, $NewValue, $str, $count);如果($count > 0){回声 $str ."<br>";if($this->InstanceSessionHandlerCustom->write($SessionId, $str))返回配置::RET_OK;}}}返回配置::RET_ERROR;}
您可以修改另一个用户会话(见下文),尽管我个人建议不要这样做.正如我想象的那样,它可以打开一个充满会话劫持和其他漏洞的世界.
以您的示例用例
一个普通用户被登录,同时管理员使用管理功能并为此用户更改一些值.如果该值不是每次都从数据库中获取的值,则需要更改当前登录用户的会话变量的值.
您最好更新数据库中的值,然后在处理下一页之前检查它是否已更改.如果您不想在每个页面加载之前检查多个用户字段,那么当您在管理面板中更新用户时,您可以构建值的哈希并将其添加到名为 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
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
这篇关于PHP 会话:如何编辑其他用户的会话/编辑会话文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!