Google crawler, cron and codeigniter sessions

2019-06-06 11:30发布

I am running a Codeigniter 2.0 web app, and I am using the sessions library with the DB option on, so for every connection on my website I have a MySQL table called 'ci_sessions' that stores:

  • Session_id
  • IP address
  • User_agent
  • Last_activity
  • User_data

And I have two issues:

  1. Google bot with IP 66.249.72.152
  2. Cron with IP 0.0.0.0

Everytime my server runs the cron or every time the google bot crawls my page a new session is created. So I have hundreds of identical sessions with the IP 0.0.0.0 and hundreds with the IP 66.249.72.152.

Does anyone know how to stop the bot or the cron from creating sessions? Or if this can not be done... does anyone know how to automatically delete these sessions every once in a while? Thanks!

4条回答
爷的心禁止访问
2楼-- · 2019-06-06 11:42

In case you want to look at this using the user agent I created a library drop in, to block bots by their user-agent, using a simple $this->agent->is_robot() check for drop in session extension.

https://github.com/donjakobo/codeigniter-clean-sessions

查看更多
虎瘦雄心在
3楼-- · 2019-06-06 11:45

A possible solution could be to implement a blacklist of IP's that a session should not be created for.

I have created two methods of doing this:

application/config/config.php

/*
|--------------------------------------------------------------------------
| Session Variables
|--------------------------------------------------------------------------
|
| 'sess_cookie_name'        = the name you want for the cookie
| 'sess_expiration'         = the number of SECONDS you want the session to last.
|   by default sessions last 7200 seconds (two hours).  Set to zero for no expiration.
| 'sess_expire_on_close'    = Whether to cause the session to expire automatically
|   when the browser window is closed
| 'sess_encrypt_cookie'     = Whether to encrypt the cookie
| 'sess_use_database'       = Whether to save the session data to a database
| 'sess_table_name'         = The name of the session database table
| 'sess_match_ip'           = Whether to match the user's IP address when reading the session data
| 'sess_match_useragent'    = Whether to match the User Agent when reading the session data
| 'sess_time_to_update'     = how many seconds between CI refreshing Session Information
| 'sess_ignore_ip'          = array of IP addresses to ignore
|
*/
$config['sess_cookie_name']     = 'ci_session';
$config['sess_expiration']      = 7200;
$config['sess_expire_on_close'] = FALSE;
$config['sess_encrypt_cookie']  = FALSE;
$config['sess_use_database']    = FALSE;
$config['sess_table_name']      = 'ci_sessions';
$config['sess_match_ip']        = FALSE;
$config['sess_match_useragent'] = TRUE;
$config['sess_time_to_update']  = 300;
$config['sess_ignore_ip']       = array('66.249.72.152', '0.0.0.0');

system/libraries/session.php

/**
 * Session Constructor
 *
 * The constructor runs the session routines automatically
 * whenever the class is instantiated.
 */
public function __construct($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_expire_on_close', 'sess_match_ip', 'sess_match_useragent', 'sess_cookie_name', 'cookie_path', 'cookie_domain', 'cookie_secure', 'sess_time_to_update', 'time_reference', 'cookie_prefix', 'encryption_key', 'sess_ignore_ip') as $key)
    {
        $this->$key = (isset($params[$key])) ? $params[$key] : $this->CI->config->item($key);
    }

    if ($this->encryption_key == '')
    {
        show_error('In order to use the Session class you are required to set an encryption key in your config file.');
    }

    // 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;

    $ip_address = $this->CI->input->ip_address();
    if(!isset($this->sess_ignore_ip) || empty($this->sess_ignore_ip) || !in_array($ip_address, $this->sess_ignore_ip))
    {
        // 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");
}

/**
 * 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}");
        if(isset($this->sess_ignore_ip) && !empty($this->sess_ignore_ip))
            $this->db->where_in('ip_address', $this->sess_ignore_ip);
        $this->CI->db->delete($this->sess_table_name);

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

The config file contains an array of IP addresses to ignore.

In the session library, I have updated the constructor, so that it checks to see if the current IP address exists in the above config setting and if so, skips the code that creates or updates the session.

In addition to this, in _sess_gc I have added new where_in statement that will delete all session rows that have an IP that matches those in the config. If you implement the constructor method, you don't really need this part.

查看更多
混吃等死
4楼-- · 2019-06-06 11:52

I suggest not to modify core files, I recommend to extend the session class, so do the next thing create MY_Session.php file in ./app/libraries/ and paste the next code

<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
/**
 * ------------------------------------------------------------------------
 * CI Session Class Extension
 * ------------------------------------------------------------------------
 *
*/
class MY_Session extends CI_Session {
   /**
    * sess_update()
    * 
    * Do not create session if it's in the cli environment
    *
    * @access    public
    * @return    void
    */
    public function sess_create() 
    {
        $CI         = get_instance();
        $ip_address = $CI->input->ip_address();

        if ( ($ip_address != '0.0.0.0' && $CI->input->user_agent() != '0') || $ip_address != '66.249.72.152'){
            parent::sess_create();
        }
    }
}

/* End of file MY_Session.php */
/* Location: ./app/libraries/MY_Session.php */
?>

this works

查看更多
The star\"
5楼-- · 2019-06-06 12:04

Alter your ci_sessions table and add the UNIQUE constraint to ip_address field. That way there will be no duplicate sessions..

A more complicated approach would be to use a trigger on insert. That will check whether the ip address is among the two addresses that you mentioned above. If yes, then donot insert in the db..

查看更多
登录 后发表回答