【问题标题】:An user access to session of another user一个用户访问另一个用户的会话
【发布时间】:2017-11-10 11:23:58
【问题描述】:

晚上好,我告诉你我的问题。我有一个用 PHP 开发的应用程序,Codeigniter 在 Wiroos 的网络托管上运行。一切正常,但随着时间的推移,应用程序有更多的用户同时访问(显然)并且开始出现以下问题。

当用户 A 从位置 A 登录时,会生成会话 A。如果同时来自位置 B 的用户 B 访问该应用程序,则用户 A 的会话会自动加载到其位置 B 中……这可能吗?

我给你看我的应用程序代码,看看你能不能帮到我

登录控制器

public function index($estadoLogin = 0){

if($this->session->userdata('estado_sesion'))
{
    redirect(base_url()."panel");
}
$data['estadoLogin'] = $estadoLogin;
$data['title'] = "Iniciar Sesión - LandingApp";
$data['bodyClass'] = "external-page sb-l-c sb-r-c";

$this->load->view('templates/header',$data);        
$this->load->view('login/loginbox', $data);

}//End method index

登录方式

public function ingresar(){
$correo = $this->security->xss_clean(strip_tags($this->input->post('correo')));
$pass = md5($this->security->xss_clean(strip_tags($this->input->post('password'))));

$Usuarios = new Usuario_Model();
$result = $Usuarios->login($correo, $pass);
if(count($result)>0){
    foreach($result as $u){
        $this->session->unset_userdata('id');
        $this->session->unset_userdata('mail');
        $this->session->unset_userdata('nombre');
        $this->session->unset_userdata('activo');
        $this->session->unset_userdata('logo_empresa');
        $this->session->unset_userdata('nombre_empresa');
        $this->session->unset_userdata('id_empresa');
        $this->session->unset_userdata('nivel');
        $this->session->unset_userdata('estado_sesion');

        $this->session->set_userdata('id', $u->id);
        $this->session->set_userdata('mail', $u->mail);
        $this->session->set_userdata('nombre', $u->nombre);
        $this->session->set_userdata('activo', $u->activo);
        $this->session->set_userdata('nivel', $u->nivel);
        $this->session->set_userdata('nombre_empresa', $u->nombre_empresa);
        $this->session->set_userdata('id_empresa', $u->id_empresa);
        $this->session->set_userdata('logo_empresa', $u->logo_empresa);
        $this->session->set_userdata('avatar_user', $u->avatar_user);
        $this->session->set_userdata('estado_sesion', TRUE);

        redirect(base_url()."panel");

    }//End foreach


}else{
    $this->session->set_flashdata('mensaje', 'El usuario o password es incorrecto');
    redirect(base_url()."login/index/1");
    //$this->index(1);
}//End if

面板控制器

public function index(){


$id = $this->session->userdata('id');
$id_empresa = $this->session->userdata('id_empresa');

$data_session['title'] = "Panel General";
$data_session['opcionMenu'] = "panel";
$data_session['bodyClass'] = "dashboard-page";

$data_session = $this->session_data_lib->set_data_session($data_session); //cargo las variables de sesion

if ($data_session['nivel']==1 || $data_session['nivel']==2){

    $data_counters = $this->counters_lib->get_admin_counters(); //cargo las variables de contadores

}else{
    $data_counters = $this->counters_lib->get_user_counters(); //cargo las variables de contadores
}

$this->load->view('templates/header', $data_session);
$this->load->view('templates/menu_top', $data_session);
$this->load->view('templates/menu_left', $data_counters);
if ($data_session['nivel']==0) {
    $this->load->view('panel/panel_user',$data_counters);
}else{
    $this->load->view('panel/panel_admin',$data_counters);
}

$this->load->view('templates/footer',$data_counters);

}//End method index

Session_Data_lib > set_data_session

public function set_data_session($data_session){
$data_lib_session['title'] = $data_session['title'];
$data_lib_session['opcionMenu'] = $data_session['opcionMenu'];
$data_lib_session['bodyClass'] = $data_session['bodyClass']; 
$data_lib_session['nombre'] = $this->CI->session->userdata('nombre');
$data_lib_session['userid'] = $this->CI->session->userdata('id');
$data_lib_session['nivel'] = $this->CI->session->userdata('nivel');   
$data_lib_session['avatar_user'] = $this->CI->session->userdata('avatar_user');
$data_lib_session['logo_empresa'] = $this->CI->session->userdata('logo_empresa');
$data_lib_session['nombre_empresa'] = $this->CI->session->userdata('nombre_empresa');
$data_lib_session['id_empresa'] = $this->CI->session->userdata('id_empresa');
$data_lib_session['arr_css'] = array("absolute_admin/assets/fonts/iconsweets/iconsweets.css");
$data_lib_session['lastSegs'] = $this->CI->panel_model->get10LastSeg($this->CI->session->userdata('id_empresa'));

return $data_lib_session;
}//End method set_data_session

我尝试将Codeigniter迁移到3.0版本,甚至在application/config/config.php中进行如下配置

$config['sess_driver'] = 'database';
$config['sess_cookie_name'] = 'ci_sessions';
$config['sess_expiration'] = 7200;
$config['sess_save_path'] = 'ci_sessions';
$config['sess_match_ip'] = TRUE;
$config['sess_time_to_update'] = 300;
$config['sess_regenerate_destroy'] = FALSE;

我不知道还有什么可以尝试的,我感觉可以是服务器配置,但除此之外我仍然没有得到支持的回应:

我们的服务器有一个由 nginx 管理的微缓存层,它可能有 导致此行为,现在我为您的域停用了它。您可以...吗 请再试一次?

显然问题仍然存在。我不明白为什么来自不同位置的两个不同用户可以在都咨询服务器时访问另一个用户的会话。希望您能帮帮我,谢谢!

【问题讨论】:

  • $pass = md5(...) MD5 哈希不再被认为是安全的,您应该考虑更改为使用password_hash php.net/manual/en/function.password-hash.php 同样在您的登录页面中,所有这些功能都应该包含在用户模型中一半。
  • 根据上述信息,我已经尽我所能审查了您的代码。现在该睡觉了。
  • 艺术凤凰,感谢您的回复!我将尝试测试您的答案,但问题可能是会话,而不是登录逻辑。我会尽快回复您
  • hash_password 而不是 md5

标签: php apache codeigniter session nginx


【解决方案1】:

正如我在 cmets 中所说,您应该更新密码以使用 PHP 的 hash_password 而不是 md5

我不能说这是您的问题,但您应该确认您的用户表中没有重复数据。这段代码

public function ingresar(){
   $correo = $this->security->xss_clean(strip_tags($this->input->post('correo')));
   $pass = md5($this->security->xss_clean(strip_tags($this->input->post('password'))));

具体来说

$this->input->post('correo')

如果$_POST 中未设置数据,CI 可以返回FALSE,因此如果出现问题,您不会检查您是否使用FALSE 作为密码和电子邮件之一或两者。例如,您应该像这样检查

public function ingresar(){
  if(!$this->input->post('correo'))
       //throw an error - stop execution, etc.
  if(!$this->input->post('password'))
       //throw an error - stop execution, etc.

  /* ...continue on if both inputs are valid ... */

如果您的数据库中没有设置唯一字段,您可能会有数十个重复用户使用相同的密码和电子邮件。都设置为false

如果不知道您对用户表的数据库字段设置了哪些约束,我无法说出这一点。但是,如果您没有适当的限制,那么可能会有多个用户使用密码false 和电子邮件false(至少根据您的登录代码),这将传递到您的数据库查找中并提取多个结果。

唯一确定的方法是在 PhpMyAdmin 中查看您的用户表,看看您是否有重复的密码和电子邮件。

还与多个用户一致,您不仅限于登录 1 个帐户。考虑这部分代码。

public function ingresar(){
    /* ..... */
    if(count($result)>0){  //should expect only one user returned.
        foreach($result as $u){

这里的循环意味着我们期待一个或多个返回记录。如果返回超过 1 个用户,这应该会引发错误。电子邮件应该是唯一的,在通过电子邮件查找用户时,我们绝不应该返回 2 个或更多用户。 (再次没有看到您的用户模型的实现,我只能猜测)。但是你应该像这样明确地检查:

public function ingresar(){
    /* ..... */
    if(count($result)==1){ 
     //log user in
    }else if(count($result)>1){
       //this should never happen but it is, so you should pay attention here
    }else{
       //user not found or wrong password.
    }

您在那里的循环可能会发生的事情是会话数据将被覆盖,直到最后一个重复记录。因此,每个拥有“不良”帐户的人都会作为不良电子邮件数据提取的最后一条记录登录。

总而言之,我会说您的代码中有很多“漏洞”可能会在适当的条件下发生这种情况。其中大部分是“猜测”,基于我所看到的您为登录而设置的松散约束。登录是您的应用程序的网关,应该比这个更紧。

附言。我使用了谷歌翻译,所以我希望我能正确阅读所有内容。

【讨论】:

    【解决方案2】:

    感谢您的回复。问题是由 NGINX 管理的微缓存层。我的托管支持禁用了该功能,一切正常!

    【讨论】:

      猜你喜欢
      • 2011-09-23
      • 2020-03-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-29
      • 2010-11-27
      • 1970-01-01
      • 2011-06-08
      相关资源
      最近更新 更多