Kenichi Ando
neo.k****@gmail*****
2008年 1月 11日 (金) 19:54:29 JST
bossatamaです。 sessionクラスを継承する方法で、以下を実装してみました。 携帯で実際に動くカウンタです。 http://codeigniter.jp/mobile/session/ URIは次のようになります: http://codeigniter.jp/mobile/session/SESSID=**************** libraries/My_Session.php <?php if (!defined('BASEPATH')) exit('No direct script access allowed'); class MY_Session extends CI_Session { var $couldnt_read_cookie = FALSE; function MY_Session() { parent::CI_Session(); } /** * Fetch the current session data if it exists * * @access public * @return void */ function sess_read() { // Fetch the cookie $session = $this->CI->input->cookie($this->sess_cookie); if ($session === FALSE) { //Remember that I couldn't read the cookie $this->couldnt_read_cookie = TRUE; //Attempt to load sess_id from url $url_session = array(); preg_match ( "|SESSID=[^/\\\\]*|", $this->CI->uri->segment ( $this->CI->uri->total_segments() ), $url_session ); if (empty ( $url_session )) { log_message('debug', 'A session cookie was not found.'); return FALSE; } else { log_message('debug', 'No session cookie found but retrieved id from url.'); $sessid = str_replace ( "SESSID=", "", $url_session[0] ); if ($this->use_database === TRUE) { $this->CI->db->select ( "userdata" ); $this->CI->db->from ( $this->session_table ); $this->CI->db->where ( 'session_id', $sessid ); $q = $this->CI->db->get(); if ($q->num_rows() > 0) { $r = $q->row(); $session = $r->userdata; } else { log_message('debug', "SESSID doesn't match. Possible hacking attempt"); return FALSE; } } else { //Create some dummy session data which will be considered as a hacking attempt //Unfortunately this solution relies on DB sessions $session["session_id"] = $sessid; $session = serialize ($session); } } } // Decrypt and unserialize the data if ($this->encryption == TRUE) { $session = $this->CI->encrypt->decode($session); } $session = @unserialize($this->strip_slashes($session)); if (!is_array($session) OR !isset($session['last_activity'])) { log_message('error', 'The session cookie data did not contain a valid array. This could be a possible hacking attempt.'); return FALSE; } // Is the session current? if (($session['last_activity'] + $this->sess_length) < $this->now) { $this->sess_destroy(); return FALSE; } // Does the IP Match? 携帯電話ではIPアドレスがころころ変わるのでNG /* if ($this->CI->config->item('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->CI->config->item('sess_match_useragent') == TRUE AND $session['user_agent'] != substr($this->CI->input->user_agent(), 0, 50)) { $this->sess_destroy(); return FALSE; } // Is there a corresponding session in the DB? if ($this->use_database === TRUE) { $this->CI->db->where('session_id', $session['session_id']); /*携帯電話ではIPアドレスがころころ変わるのでNG if ($this->CI->config->item('sess_match_ip') == TRUE) { $this->CI->db->where('ip_address', $session['ip_address']); } */ if ($this->CI->config->item('sess_match_useragent') == TRUE) { $this->CI->db->where('user_agent', $session['user_agent']); } $query = $this->CI->db->get($this->session_table); if ($query->num_rows() == 0) { $this->sess_destroy(); return FALSE; } else { $row = $query->row(); if (($row->last_activity + $this->sess_length) < $this->now) { $this->CI->db->where('session_id', $session['session_id']); $this->CI->db->delete($this->session_table); $this->sess_destroy(); return FALSE; } } } // Session is valid! $this->userdata = $session; unset($session); return TRUE; } /** * Write the session cookie * * @access public * @return void */ function sess_write() { parent::sess_write(); //If I couldn't read the cookie last time, attach session data to //url in case I can't read the cookie in future attempts //This functionality demands that URLs are created using CI //tools such as URL helper or reminding to always attach the url //suffix (even if you don't define one if ( $this->couldnt_read_cookie ) { //Unset in case we rewrite the session $this->couldn_read_cookie = FALSE; $this->CI->config->set_item ( 'url_suffix','/SESSID=' . $this->userdata ( 'session_id' ) . config_item ( 'url_suffix' ) ); } //Save userdata in database if ($this->use_database === TRUE) { $set = array ( "session_id" => $this->userdata ( 'session_id' ), "ip_address" => $this->userdata ( 'ip_address' ), "user_agent" => $this->userdata ( 'user_agent' ), "last_activity" => $this->userdata ( 'last_activity' ), "userdata" => serialize ( $this->userdata ) ); $this->CI->db->where ( "session_id", $this->userdata ( 'session_id' ) ); $this->CI->db->update ( $this->session_table, $set ); } } } ?> このセッションはDB必須です。 CREATE TABLE `ci_sessions` ( `session_id` varchar(40) NOT NULL default '0', `ip_address` varchar(16) NOT NULL default '0', `user_agent` varchar(50) NOT NULL default '', `last_activity` int(10) unsigned NOT NULL default '0', `userdata` text NOT NULL, PRIMARY KEY (`session_id`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8; config/config.phpでDBに変更する $config['sess_use_database'] = TRUE; URIセグメントパターンに「=」を追加します。 $config['permitted_uri_chars'] = '= a-z 0-9~%.:_-'; config/routes.phpでルーティングを変更させます。 $route ['(.*)SESSID=.*$'] = "$1"; 携帯なんで、Shift_JISでもいけるように英文に修正 controllers/session.php <?php class Session extends Controller { function Session() { parent::Controller(); $this->load->library('session'); $this->load->helper('url'); } function index() { if (!$this->session->userdata('conut')) { $this->session->set_userdata('conut', 1); } else { $count = $this->session->userdata('conut'); $count++; $this->session->set_userdata('conut', $count); } echo 'SESSIONID:' . $this->session->userdata('session_id') . '<br>'; echo 'COUNTER:' . $this->session->userdata('conut') . '<br>'; echo anchor('/session', 'RELOAD'); } } ?> SESSIDが自動的に付加されます。