lichao032100 发表于 2009-10-29 16:05:26

hex伤心了 又不是解决不掉

doom12 发表于 2009-11-6 16:22:24

本帖最后由 doom12 于 2009-11-6 16:35 编辑

这样是否可行:
改写Output 的 cache 函数, 将cache的MD5标识从URI改成自定义,cache 完全有 controller 控制,
优点: 自己能控制 cache,有很多情况下uri反映不了问题
缺点: 在controller层,效率差一点。

<?
if ( ! defined('BASEPATH')) exit('No direct script access allowed');
class MY_Output extends CI_Output {
        var $id_str='';
        var $c_dir='';
       
        function My_output()
    {
      parent::CI_output();
    }
   
        function _write_cache($output)
        {
                $CI =& get_instance();       
                $path = $CI->config->item('cache_path');
       
                $cache_path = ($path == '') ? BASEPATH.'cache/' : $path;
               
                if ( ! is_dir($cache_path) OR ! is_really_writable($cache_path))
                {
                        return;
                }
               
                if($this->c_dir!=='') $cache_path = $cache_path.$this->c_dir."/";
               
                $cache_path .= md5($this->id_str);

                if ( ! $fp = @fopen($cache_path, FOPEN_WRITE_CREATE_DESTRUCTIVE))
                {
                        log_message('error', "Unable to write cache file: ".$cache_path);
                        return;
                }
               
                $expire = time() + ($this->cache_expiration * 60);
               
                if (flock($fp, LOCK_EX))
                {
                        fwrite($fp, $expire.'TS--->'.$output);
                        flock($fp, LOCK_UN);
                }
                else
                {
                        log_message('error', "Unable to secure a file lock for file at: ".$cache_path);
                        return;
                }
                fclose($fp);
                @chmod($cache_path, DIR_WRITE_MODE);

                log_message('debug', "Cache file written: ".$cache_path);
        }
       
function _display_cache()
{ // don't search cache file by URI
        return FALSE;
}

function _display_cache_si()
        {   $CI =& get_instance();       
                $path = $CI->config->item('cache_path');
       
                $cache_path = ($path == '') ? BASEPATH.'cache/' : $path;
                if($this->c_dir!=='') $cache_path = $cache_path.$this->c_dir."/";
                       
                if ( ! is_dir($cache_path) OR ! is_really_writable($cache_path))
                {
                        return FALSE;
                }
               
               
                // Build the file path.The file name is an MD5 hash of the full URI
               
                                       
                $filepath = $cache_path.md5($this->id_str);
               
                if ( ! @file_exists($filepath))
                {
                        return FALSE;
                }
       
                if ( ! $fp = @fopen($filepath, FOPEN_READ))
                {
                        return FALSE;
                }
                       
                flock($fp, LOCK_SH);
               
                $cache = '';
                if (filesize($filepath) > 0)
                {
                        $cache = fread($fp, filesize($filepath));
                }
       
                flock($fp, LOCK_UN);
                fclose($fp);
                                       
                // Strip out the embedded timestamp               
                if ( ! preg_match("/(\d+TS--->)/", $cache, $match))
                {
                        return FALSE;
                }
               
                // Has the file expired? If so we'll delete it.
                if (time() >= trim(str_replace('TS--->', '', $match['1'])))
                {                
                        @unlink($filepath);
                        log_message('debug', "Cache file has expired. File deleted");
                        return FALSE;
                }
               
      $this->cache_expiration        = 0; // set to 0 provent from rewrite cache
      
                // Display the cache
                $this->_display(str_replace($match['0'], '', $cache));
                log_message('debug', "Cache file is current. Sending it to browser.");               
                return TRUE;
        }

    function cache($m_id,$time)
        {   $this->id_str=( ! is_string($m_id)) ? '' : $m_id;
                $this->cache_expiration = ( ! is_numeric($time)) ? 0 : $time;
               
                return($this->_display_cache_si());
        }
       
        function cache_dir($m_id,$time,$m_dir)
        {   $this->id_str=( ! is_string($m_id)) ? '' : $m_id;
          $this->c_dir=( ! is_string($m_dir)) ? '' : $m_dir;
                $this->cache_expiration = ( ! is_numeric($time)) ? 0 : $time;
               
                return($this->_display_cache_si());
        }
}


在 controller 里 的 method 里 开始处加入

if($this->output->cache($cache_id,$expire_time))return;
或者
if($this->output->cache_dir($cache_id,$expire_time,$cache_dir))return;

$cache_id 可以用method 的参数+自己赋予的唯一标示串组成
$cache_dir 则是在 系统 cache 里建立的2级目录,用于分散cache文件

ci02576120 发表于 2011-12-15 16:28:13

本人为 CI初学者 看到这篇“长长”的讨论感觉收益颇丰,在以后用到的时候会再度拿出来看看,谢谢楼主和各位高手的阐述。

buaixiaofei 发表于 2012-2-28 16:26:16

看到本帖的讨论,再看了下本帖的主题,发现大家讨论的内容偏了。版主的意思没偏,大伙说偏了。但是从大家的讨论中学习到了不少。继续支持Codeigniter中国论坛。

alex_shen 发表于 2012-3-11 17:33:12

嗯,要使用的话,可以配合自己的model强制url的检测。

justdoit 发表于 2012-3-12 09:33:47

楼主真是细心啊,顶。:kiss:

自然 发表于 2012-3-12 11:14:47

mark{:1_1:}

lynn.wang 发表于 2012-3-12 11:59:27

Chrome都被攻陷了~~~

屠城 发表于 2012-4-15 23:31:16

visvoy 发表于 2009-4-8 07:57 static/image/common/back.gif
解决办法:
1. 先扩展URI类



好。。。:D

指尖的殤魂 发表于 2012-4-16 17:17:49

2.1了 这个问题还是有哦
页: 1 2 3 4 5 6 7 8 9 [10] 11 12
查看完整版本: 脆弱的CI缓存系统,1天攻陷你的CI网站