Jump to content
Fórum Script Brasil
  • 0

Logout por inatividade.


LincolnSMelo

Question

Olá.

Estou nas etapas finais da criação de um site feito na plataforma PHP. Utilizo banco de dados Mysql, e sempre que algum usuário faz Log IN em sua conta, o número "1" é setado na table "online" no bd e sempre que fazem Log OUT, é setado "0". Como podem ver, isso é uma forma que criei para checar quem está online no site. Eu uso várias funções que pedem em variáveis o valor deste "online".

Acontece que caso todos os usuários saíssem do site pelo botão "Log OUT", eu não teria problema, mas o que realmente acontece, é que os usuários simplesmente fecham a página sem dar logout,e, consequentemente, a table "online" no db sempre fica setado "1", até que ele retorne e dê logout.

alguém aqui pode me ajudar a construir um código para finalizar a sessão e dar logout no usuário? Ou simplesmente setar no db esta variável?

Obrigado.

Link to comment
Share on other sites

3 answers to this question

Recommended Posts

  • 0

Amigo já fiz algo parecido a muito tempo, utilizando jQuery, eu implementava, em qualquer página que o usuário estive-se usando, uma função que era executada automaticamente, a cada 1 minuto, mandando para o servidor, a seguinte informação, o ID do usuário no banco para uma classe PHP.

Na minha classe PHP, eu fazia um INSERT, na tabela, tbusuarios_ativos (ou um UPDATE, atualizando a data de registro). Assim, quando eu queria monitorar, os usuários que estão online, eu faço uma consulta no banco, excluindo os usuários que possuem registro com a data muito antiga, por exemplo, 2 minutos atrás.

Assim você teria com uma precisão aceitável a informação de quem realmente está ou esteve online nos últimos minutos.

Obs. Isso irá gerar um overload no servidor.

Por que Lincoln estou citando esse exemplo? Por que eu não vejo como pegar o exato momento que a internet do usuário caiu ou fechou o navegador, se você não possuir um "processo" que monitore as atividades de seu usuário.

Link to comment
Share on other sites

  • 0
Amigo já fiz algo parecido a muito tempo, utilizando jQuery, eu implementava, em qualquer página que o usuário estive-se usando, uma função que era executada automaticamente, a cada 1 minuto, mandando para o servidor, a seguinte informação, o ID do usuário no banco para uma classe PHP.

Na minha classe PHP, eu fazia um INSERT, na tabela, tbusuarios_ativos (ou um UPDATE, atualizando a data de registro). Assim, quando eu queria monitorar, os usuários que estão online, eu faço uma consulta no banco, excluindo os usuários que possuem registro com a data muito antiga, por exemplo, 2 minutos atrás.

Assim você teria com uma precisão aceitável a informação de quem realmente está ou esteve online nos últimos minutos.

Obs. Isso irá gerar um overload no servidor.

Por que Lincoln estou citando esse exemplo? Por que eu não vejo como pegar o exato momento que a internet do usuário caiu ou fechou o navegador, se você não possuir um "processo" que monitore as atividades de seu usuário.

Olá, obrigado por responder.

Eu utilizo um sistema de SESSIONS que funciona perfeitamente, nele, caso você faça login e feche o navegador, ele desloga o usuário. Mas não estou encontrando onde fica este sistema para que eu posso adicionar minha função de alterar no bd quando isso acontecer. O sistema de sessions e onde fica o sess_destroy(). O que eu preciso é implementar uma linha de código que altera no bd o valor de 1 para 0, quando o usuário fechar o navegador. Abaixo está o cógido sessions.php que encontra-se em meu site :

<?php  if ( ! defined('BASEPATH')) exit('No direct script access allowed');
/**
 * CodeIgniter
 *
 * An open source application development framework for PHP 4.3.2 or newer
 *
 * @package        CodeIgniter
 * @author        ExpressionEngine Dev Team
 * @copyright    Copyright (c) 2008 - 2009, EllisLab, Inc.
 * @license        http://codeigniter.com/user_guide/license.html
 * @link        http://codeigniter.com
 * @since        Version 1.0
 * @filesource
 */

// ------------------------------------------------------------------------

/**
 * Session Class
 *
 * @package        CodeIgniter
 * @subpackage    Libraries
 * @category    Sessions
 * @author        ExpressionEngine Dev Team
 * @link        http://codeigniter.com/user_guide/libraries/sessions.html
 */
class CI_Session {

    var $sess_encrypt_cookie        = FALSE;
    var $sess_use_database            = FALSE;
    var $sess_table_name            = '';
    var $sess_expiration            = 7200;
    var $sess_match_ip                = FALSE;
    var $sess_match_useragent        = TRUE;
    var $sess_cookie_name            = 'ci_session';
    var $cookie_prefix                = '';
    var $cookie_path                = '';
    var $cookie_domain                = '';
    var $sess_time_to_update        = 300;
    var $encryption_key                = '';
    var $flashdata_key                 = 'flash';
    var $time_reference                = 'time';
    var $gc_probability                = 5;
    var $userdata                    = array();
    var $CI;
    var $now;

    /**
     * Session Constructor
     *
     * The constructor runs the session routines automatically
     * whenever the class is instantiated.
     */
    function CI_Session($params = array())
    {
        log_message('debug', "Session Class Initialized");

        // Set the super object to a local variable for use throughout the class
        $this->CI =& get_instance();

        // Set all the session preferences, which can either be set
        // manually via the $params array above or via the config file
        foreach (array('sess_encrypt_cookie', 'sess_use_database', 'sess_table_name', 'sess_expiration', 'sess_match_ip', 'sess_match_useragent', 'sess_cookie_name', 'cookie_path', 'cookie_domain', 'sess_time_to_update', 'time_reference', 'cookie_prefix', 'encryption_key') as $key)
        {
            $this->$key = (isset($params[$key])) ? $params[$key] : $this->CI->config->item($key);
        }

        // Load the string helper so we can use the strip_slashes() function
        $this->CI->load->helper('string');

        // Do we need encryption? If so, load the encryption class
        if ($this->sess_encrypt_cookie == TRUE)
        {
            $this->CI->load->library('encrypt');
        }

        // Are we using a database?  If so, load it
        if ($this->sess_use_database === TRUE AND $this->sess_table_name != '')
        {
            $this->CI->load->database();
        }

        // Set the "now" time.  Can either be GMT or server time, based on the
        // config prefs.  We use this to set the "last activity" time
        $this->now = $this->_get_time();

        // Set the session length. If the session expiration is
        // set to zero we'll set the expiration two years from now.
        if ($this->sess_expiration == 0)
        {
            $this->sess_expiration = (60*60*24*365*2);
        }
         
        // Set the cookie name
        $this->sess_cookie_name = $this->cookie_prefix.$this->sess_cookie_name;

        // Run the Session routine. If a session doesn't exist we'll
        // create a new one.  If it does, we'll update it.
        if ( ! $this->sess_read())
        {
            $this->sess_create();
        }
        else
        {
            $this->sess_update();
        }

        // Delete 'old' flashdata (from last request)
           $this->_flashdata_sweep();

        // Mark all new flashdata as old (data will be deleted before next request)
           $this->_flashdata_mark();

        // Delete expired sessions if necessary
        $this->_sess_gc();

        log_message('debug', "Session routines successfully run");
    }

    // --------------------------------------------------------------------

    /**
     * Fetch the current session data if it exists
     *
     * @access    public
     * @return    bool
     */
    function sess_read()
    {
        // Fetch the cookie
        $session = $this->CI->input->cookie($this->sess_cookie_name);

        // No cookie?  Goodbye cruel world!...
        if ($session === FALSE)
        {
            log_message('debug', 'A session cookie was not found.');
            return FALSE;
        }

        // Decrypt the cookie data
        if ($this->sess_encrypt_cookie == TRUE)
        {
            $session = $this->CI->encrypt->decode($session);
        }
        else
        {
            // encryption was not used, so we need to check the md5 hash
            $hash     = substr($session, strlen($session)-32); // get last 32 chars
            $session = substr($session, 0, strlen($session)-32);

            // Does the md5 hash match?  This is to prevent manipulation of session data in userspace
            if ($hash !==  md5($session.$this->encryption_key))
            {
                log_message('error', 'The session cookie data did not match what was expected. This could be a possible hacking attempt.');
                $this->sess_destroy();
                return FALSE;
            }
        }

        // Unserialize the session array
        $session = $this->_unserialize($session);

        // Is the session data we unserialized an array with the correct format?
        if ( ! is_array($session) OR ! isset($session['session_id']) OR ! isset($session['ip_address']) OR ! isset($session['user_agent']) OR ! isset($session['last_activity']))
        {
            $this->sess_destroy();
            return FALSE;
        }

        // Is the session current?
        if (($session['last_activity'] + $this->sess_expiration) < $this->now)
        {
            $this->sess_destroy();
            return FALSE;
        }

        // Does the IP Match?
        if ($this->sess_match_ip == TRUE AND $session['ip_address'] != $this->CI->input->ip_address())
        {
            $this->sess_destroy();
            return FALSE;
        }

        // Does the User Agent Match?
        if ($this->sess_match_useragent == TRUE AND trim($session['user_agent']) != trim(substr($this->CI->input->user_agent(), 0, 50)))
        {
            $this->sess_destroy();
            return FALSE;
        }

        // Is there a corresponding session in the DB?
        if ($this->sess_use_database === TRUE)
        {
            $this->CI->db->where('session_id', $session['session_id']);

            if ($this->sess_match_ip == TRUE)
            {
                $this->CI->db->where('ip_address', $session['ip_address']);
            }

            if ($this->sess_match_useragent == TRUE)
            {
                $this->CI->db->where('user_agent', $session['user_agent']);
            }

            $query = $this->CI->db->get($this->sess_table_name);

            // No result?  Kill it!
            if ($query->num_rows() == 0)
            {
                $this->sess_destroy();
                return FALSE;
            }

            // Is there custom data?  If so, add it to the main session array
            $row = $query->row();
            if (isset($row->user_data) AND $row->user_data != '')
            {
                $custom_data = $this->_unserialize($row->user_data);

                if (is_array($custom_data))
                {
                    foreach ($custom_data as $key => $val)
                    {
                        $session[$key] = $val;
                    }
                }
            }
        }

        // Session is valid!
        $this->userdata = $session;
        unset($session);

        return TRUE;
    }

    // --------------------------------------------------------------------

    /**
     * Write the session data
     *
     * @access    public
     * @return    void
     */
    function sess_write()
    {
        // Are we saving custom data to the DB?  If not, all we do is update the cookie
        if ($this->sess_use_database === FALSE)
        {
            $this->_set_cookie();
            return;
        }

        // set the custom userdata, the session data we will set in a second
        $custom_userdata = $this->userdata;
        $cookie_userdata = array();

        // Before continuing, we need to determine if there is any custom data to deal with.
        // Let's determine this by removing the default indexes to see if there's anything left in the array
        // and set the session data while we're at it
        foreach (array('session_id','ip_address','user_agent','last_activity') as $val)
        {
            unset($custom_userdata[$val]);
            $cookie_userdata[$val] = $this->userdata[$val];
        }

        // Did we find any custom data?  If not, we turn the empty array into a string
        // since there's no reason to serialize and store an empty array in the DB
        if (count($custom_userdata) === 0)
        {
            $custom_userdata = '';
        }
        else
        {
            // Serialize the custom data array so we can store it
            $custom_userdata = $this->_serialize($custom_userdata);
        }

        // Run the update query
        $this->CI->db->where('session_id', $this->userdata['session_id']);
        $this->CI->db->update($this->sess_table_name, array('last_activity' => $this->userdata['last_activity'], 'user_data' => $custom_userdata));

        // Write the cookie.  Notice that we manually pass the cookie data array to the
        // _set_cookie() function. Normally that function will store $this->userdata, but
        // in this case that array contains custom data, which we do not want in the cookie.
        $this->_set_cookie($cookie_userdata);
    }

    // --------------------------------------------------------------------

    /**
     * Create a new session
     *
     * @access    public
     * @return    void
     */
    function sess_create()
    {
        $sessid = '';
        while (strlen($sessid) < 32)
        {
            $sessid .= mt_rand(0, mt_getrandmax());
        }

        // To make the session ID even more secure we'll combine it with the user's IP
        $sessid .= $this->CI->input->ip_address();

        $this->userdata = array(
                            'session_id'     => md5(uniqid($sessid, TRUE)),
                            'ip_address'     => $this->CI->input->ip_address(),
                            'user_agent'     => substr($this->CI->input->user_agent(), 0, 50),
                            'last_activity'    => $this->now
                            );


        // Save the data to the DB if needed
        if ($this->sess_use_database === TRUE)
        {
            $this->CI->db->query($this->CI->db->insert_string($this->sess_table_name, $this->userdata));
        }

        // Write the cookie
        $this->_set_cookie();
    }

    // --------------------------------------------------------------------

    /**
     * Update an existing session
     *
     * @access    public
     * @return    void
     */
    function sess_update()
    {
        // We only update the session every five minutes by default
        if (($this->userdata['last_activity'] + $this->sess_time_to_update) >= $this->now)
        {
            return;
        }

        // Save the old session id so we know which record to
        // update in the database if we need it
        $old_sessid = $this->userdata['session_id'];
        $new_sessid = '';
        while (strlen($new_sessid) < 32)
        {
            $new_sessid .= mt_rand(0, mt_getrandmax());
        }

        // To make the session ID even more secure we'll combine it with the user's IP
        $new_sessid .= $this->CI->input->ip_address();

        // Turn it into a hash
        $new_sessid = md5(uniqid($new_sessid, TRUE));

        // Update the session data in the session data array
        $this->userdata['session_id'] = $new_sessid;
        $this->userdata['last_activity'] = $this->now;

        // _set_cookie() will handle this for us if we aren't using database sessions
        // by pushing all userdata to the cookie.
        $cookie_data = NULL;

        // Update the session ID and last_activity field in the DB if needed
        if ($this->sess_use_database === TRUE)
        {
            // set cookie explicitly to only have our session data
            $cookie_data = array();
            foreach (array('session_id','ip_address','user_agent','last_activity') as $val)
            {
                $cookie_data[$val] = $this->userdata[$val];
            }

            $this->CI->db->query($this->CI->db->update_string($this->sess_table_name, array('last_activity' => $this->now, 'session_id' => $new_sessid), array('session_id' => $old_sessid)));
        }

        // Write the cookie
        $this->_set_cookie($cookie_data);
    }

    // --------------------------------------------------------------------

    /**
     * Destroy the current session
     *
     * @access    public
     * @return    void
     */
    function sess_destroy()
    {
        // Kill the session DB row
        if ($this->sess_use_database === TRUE AND isset($this->userdata['session_id']))
        {
            $this->CI->db->where('session_id', $this->userdata['session_id']);
            $this->CI->db->delete($this->sess_table_name);
        }

        // Kill the cookie
        setcookie(
                    $this->sess_cookie_name,
                    addslashes(serialize(array())),
                    ($this->now - 31500000),
                    $this->cookie_path,
                    $this->cookie_domain,
                    0
                );
    }

    // --------------------------------------------------------------------

    /**
     * Fetch a specific item from the session array
     *
     * @access    public
     * @param    string
     * @return    string
     */
    function userdata($item)
    {
        return ( ! isset($this->userdata[$item])) ? FALSE : $this->userdata[$item];
    }

    // --------------------------------------------------------------------

    /**
     * Fetch all session data
     *
     * @access    public
     * @return    mixed
     */
    function all_userdata()
    {
        return ( ! isset($this->userdata)) ? FALSE : $this->userdata;
    }

    // --------------------------------------------------------------------

    /**
     * Add or change data in the "userdata" array
     *
     * @access    public
     * @param    mixed
     * @param    string
     * @return    void
     */
    function set_userdata($newdata = array(), $newval = '')
    {
        if (is_string($newdata))
        {
            $newdata = array($newdata => $newval);
        }

        if (count($newdata) > 0)
        {
            foreach ($newdata as $key => $val)
            {
                $this->userdata[$key] = $val;
            }
        }

        $this->sess_write();
    }

    // --------------------------------------------------------------------

    /**
     * Delete a session variable from the "userdata" array
     *
     * @access    array
     * @return    void
     */
    function unset_userdata($newdata = array())
    {
        if (is_string($newdata))
        {
            $newdata = array($newdata => '');
        }

        if (count($newdata) > 0)
        {
            foreach ($newdata as $key => $val)
            {
                unset($this->userdata[$key]);
            }
        }

        $this->sess_write();
    }

    // ------------------------------------------------------------------------

    /**
     * Add or change flashdata, only available
     * until the next request
     *
     * @access    public
     * @param    mixed
     * @param    string
     * @return    void
     */
    function set_flashdata($newdata = array(), $newval = '')
    {
        if (is_string($newdata))
        {
            $newdata = array($newdata => $newval);
        }

        if (count($newdata) > 0)
        {
            foreach ($newdata as $key => $val)
            {
                $flashdata_key = $this->flashdata_key.':new:'.$key;
                $this->set_userdata($flashdata_key, $val);
            }
        }
    }

    // ------------------------------------------------------------------------

    /**
     * Keeps existing flashdata available to next request.
     *
     * @access    public
     * @param    string
     * @return    void
     */
    function keep_flashdata($key)
    {
        // 'old' flashdata gets removed.  Here we mark all
        // flashdata as 'new' to preserve it from _flashdata_sweep()
        // Note the function will return FALSE if the $key
        // provided cannot be found
        $old_flashdata_key = $this->flashdata_key.':old:'.$key;
        $value = $this->userdata($old_flashdata_key);

        $new_flashdata_key = $this->flashdata_key.':new:'.$key;
        $this->set_userdata($new_flashdata_key, $value);
    }

    // ------------------------------------------------------------------------

    /**
     * Fetch a specific flashdata item from the session array
     *
     * @access    public
     * @param    string
     * @return    string
     */
    function flashdata($key)
    {
        $flashdata_key = $this->flashdata_key.':old:'.$key;
        return $this->userdata($flashdata_key);
    }

    // ------------------------------------------------------------------------

    /**
     * Identifies flashdata as 'old' for removal
     * when _flashdata_sweep() runs.
     *
     * @access    private
     * @return    void
     */
    function _flashdata_mark()
    {
        $userdata = $this->all_userdata();
        foreach ($userdata as $name => $value)
        {
            $parts = explode(':new:', $name);
            if (is_array($parts) && count($parts) === 2)
            {
                $new_name = $this->flashdata_key.':old:'.$parts[1];
                $this->set_userdata($new_name, $value);
                $this->unset_userdata($name);
            }
        }
    }

    // ------------------------------------------------------------------------

    /**
     * Removes all flashdata marked as 'old'
     *
     * @access    private
     * @return    void
     */

    function _flashdata_sweep()
    {
        $userdata = $this->all_userdata();
        foreach ($userdata as $key => $value)
        {
            if (strpos($key, ':old:'))
            {
                $this->unset_userdata($key);
            }
        }

    }

    // --------------------------------------------------------------------

    /**
     * Get the "now" time
     *
     * @access    private
     * @return    string
     */
    function _get_time()
    {
        if (strtolower($this->time_reference) == 'gmt')
        {
            $now = time();
            $time = mktime(gmdate("H", $now), gmdate("i", $now), gmdate("s", $now), gmdate("m", $now), gmdate("d", $now), gmdate("Y", $now));
        }
        else
        {
            $time = time();
        }

        return $time;
    }

    // --------------------------------------------------------------------

    /**
     * Write the session cookie
     *
     * @access    public
     * @return    void
     */
    function _set_cookie($cookie_data = NULL)
    {
        if (is_null($cookie_data))
        {
            $cookie_data = $this->userdata;
        }

        // Serialize the userdata for the cookie
        $cookie_data = $this->_serialize($cookie_data);

        if ($this->sess_encrypt_cookie == TRUE)
        {
            $cookie_data = $this->CI->encrypt->encode($cookie_data);
        }
        else
        {
            // if encryption is not used, we provide an md5 hash to prevent userside tampering
            $cookie_data = $cookie_data.md5($cookie_data.$this->encryption_key);
        }

        // Set the cookie
        setcookie(
                    $this->sess_cookie_name,
                    $cookie_data,
                    $this->sess_expiration + time(),
                    $this->cookie_path,
                    $this->cookie_domain,
                    0
                );
    }

    // --------------------------------------------------------------------

    /**
     * Serialize an array
     *
     * This function first converts any slashes found in the array to a temporary
     * marker, so when it gets unserialized the slashes will be preserved
     *
     * @access    private
     * @param    array
     * @return    string
     */
    function _serialize($data)
    {
        if (is_array($data))
        {
            foreach ($data as $key => $val)
            {
                $data[$key] = str_replace('\\', '{{slash}}', $val);
            }
        }
        else
        {
            $data = str_replace('\\', '{{slash}}', $data);
        }

        return serialize($data);
    }

    // --------------------------------------------------------------------

    /**
     * Unserialize
     *
     * This function unserializes a data string, then converts any
     * temporary slash markers back to actual slashes
     *
     * @access    private
     * @param    array
     * @return    string
     */
    function _unserialize($data)
    {
        $data = @unserialize(strip_slashes($data));

        if (is_array($data))
        {
            foreach ($data as $key => $val)
            {
                $data[$key] = str_replace('{{slash}}', '\\', $val);
            }

            return $data;
        }

        return str_replace('{{slash}}', '\\', $data);
    }

    // --------------------------------------------------------------------

    /**
     * Garbage collection
     *
     * This deletes expired session rows from database
     * if the probability percentage is met
     *
     * @access    public
     * @return    void
     */
    function _sess_gc()
    {
        if ($this->sess_use_database != TRUE)
        {
            return;
        }

        srand(time());
        if ((rand() % 100) < $this->gc_probability)
        {
            $expire = $this->now - $this->sess_expiration;

            $this->CI->db->where("last_activity < {$expire}");
            $this->CI->db->delete($this->sess_table_name);

            log_message('debug', 'Session garbage collection performed.');
        }
    }


}
// END Session Class

/* End of file Session.php */
/* Location: ./system/libraries/Session.php */

Link to comment
Share on other sites

  • 0

Boa tarde Lincoln,

dei uma olhada no site dessa library

http://codeigniter.com/user_guide/libraries/sessions.html

Eu acho que isso ajuda na sua busca

Note: The Session class has built-in garbage collection which clears out expired sessions so you do not need to write your own routine to do it.

Então, ele possui uma propria função que limpa as sessions expiradas (ou usuários inativos)

Essa função é a ultima função do código que você postou

function _sess_gc()

{

if ($this->sess_use_database != TRUE)

{

return;

}

srand(time());

if ((rand() % 100) < $this->gc_probability)

{

$expire = $this->now - $this->sess_expiration;

$this->CI->db->where("last_activity < {$expire}");

$this->CI->db->delete($this->sess_table_name);

log_message('debug', 'Session garbage collection performed.');

}

}

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Answer this question...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.



  • Forum Statistics

    • Total Topics
      152.2k
    • Total Posts
      652k
×
×
  • Create New...