[Codeigniter-users] モバイルサイトのセッションについて

Back to archive index

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が自動的に付加されます。




Codeigniter-users メーリングリストの案内
Back to archive index