1

我正在运行一个Codeigniter 2.0 Web 应用程序,并且我正在使用带有 DB 选项的会话库,因此对于我网站上的每个连接,我都有一个名为'ci_sessions'存储的 MySQL 表:

  • Session_id
  • IP地址
  • 用户代理
  • 最后一个活动
  • 用户数据

我有两个问题:

  1. 带 IP 的 Google 机器人66.249.72.152
  2. 带 IP 的 Cron0.0.0.0

每次我的服务器运行 cron 或每次 google bot 抓取我的页面时,都会创建一个新会话。所以我有数百个与 IP 相同的会话0.0.0.0和数百个与 IP相同的会话66.249.72.152

有谁知道如何阻止机器人或 cron 创建会话?或者如果这不能完成......有谁知道如何每隔一段时间自动删除这些会话?谢谢!

4

4 回答 4

1

一种可能的解决方案是实施不应为其创建会话的 IP 黑名单。

我创建了两种方法来做到这一点:

应用程序/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');

系统/库/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.');
    }
}

配置文件包含要忽略的 IP 地址数组。

在会话库中,我更新了构造函数,以便它检查当前 IP 地址是否存在于上述配置设置中,如果存在,则跳过创建或更新会话的代码。

除此之外,_sess_gc我还添加了新的 where_in 语句,该语句将删除 IP 与配置中的 IP 匹配的所有会话行。如果你实现了构造方法,你就不需要这部分了。

于 2012-06-13T13:31:47.170 回答
1

我建议不要修改核心文件,我建议扩展会话类,所以接下来在./app/libraries/中创建MY_Session.php文件并粘贴下一个代码

<?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 */
?>

这行得通

于 2013-03-01T23:28:54.107 回答
0

如果您想使用 I created a library drop in 来查看这个user agent,通过他们的用户代理阻止机器人,使用简单的$this->agent->is_robot()检查 drop in session 扩展。

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

于 2013-11-19T18:15:20.300 回答
-3

更改 ci_sessions 表并将 UNIQUE 约束添加到 ip_address 字段。这样就不会有重复的会话..

更复杂的方法是在插入时使用触发器。这将检查 IP 地址是否在您上面提到的两个地址之间。如果是,则不要插入数据库..

于 2012-06-13T13:19:44.010 回答