CodeIgniter 使用手冊版本 2.2.0


Session 類別

Session類別允許你在使用者瀏覽你的網頁時, 保存使用者的"狀態"及紀錄使用者活動。Session類別將每個使用者的session資訊序列化 (並可經過加密)後, 儲存在cookie中。除此之外, 亦可將session資料儲存於資料庫表格中, 藉由比對使用者cookie中所儲存的session id 是否與資料庫中的id符合, 來增強其安全性。Session類別預設僅將session儲存於cookie當中, 若要使用資料庫來儲存, 必須依照下面指示的 方式來建立session表格。

注意: CI的Session類別採用自己建立的session資料, 而非 PHP所提供的 session, 藉此為開發者提供更佳的彈性。

Note: Even if you are not using encrypted sessions, you must set an encryption key in your config file which is used to aid in preventing session data manipulation.

初始化Session

基本上, session會在每個頁面載入後, 以全域的方式運行。Session類別可利用控制器的 建構子作初始化, 抑或是利用系統的自動載入 機制(譯注:即application/config/autoload.php檔)。大部分的情形下, session載入後便會在背景運行, 因此初始化之後, session的資 料便會自動被讀取、建立及更新。

若要在控制器的建構子裡手動初始化Session類別, 可使用$this->load->library函數:

$this->load->library('session');

一旦類別被載入, 便可透過$this->session的方式來存取Session物件

Session如何運作?

當一頁面被載入時, session類別會檢查使用者的cookie檔是否存在有效的session資料。若是存在(或是已經過期) , 則會建立一新session並儲存於cookie中;若是存在, 則該session的資訊與其cookie皆會同時被更新。而每次更新時, session_id亦會重 新被產生。

對於使用者來說, 非常重要且需要了解的一點是, Session類別一旦被初始化後, 便會自動運作, 使用者無需理會接下來的任何事情。如同 下面所示, 你可任意使用, 甚至新增自己的session資料。而在此過程中, 讀取、寫入以及更新session等動作都是自動完成的。

Session資料是什麼?

就CodeIgniter而言, 一個session是由包含下列資訊的陣列所組成。

上述資料以下列的陣列格式序列化並儲存至cookie中:

[array]
(
     'session_id'    => random hash,
     'ip_address'    => 'string - user IP address',
     'user_agent'    => 'string - user agent data',
     'last_activity' => timestamp
)

若將加密選項開啟, 則該序列化陣列會在儲存於cookie前先作加密的動作, 以避免該資料被他人讀取或是更動, 達到更高的安全性。 事實上, Session類別會自動處理資料初始化及加密的動作, 想了解更多關於加密的資訊, 可在這裡找到。

注意:為了減少處理器的負擔, Session cookie預設每5分鐘更新一次。若是持續重複載入頁面, 則"last activity"的時間值, 只有在距上次 cookie被寫入時間超過5分鐘以上才會更新。此間隔亦可藉由更改system/config/config.php檔案中的$config['sess_time_to_update']該行來作設定。

取得Session資料

Session陣列裡的任何資料, 可藉由下列函數取得:

$this->session->userdata('item');

其中item為所要取得的資料其對應的陣列索引。舉例來說, 要取得session ID, 可使用以下方式:

$session_id = $this->session->userdata('session_id');

注意: 若是所要存取的資料不存在, 則該function傳回FALSE(布林值)。

增加自訂Session資料

Session陣列一個方便的好處在於, 使用者可新增自己的資料, 該資料會儲存於該使用者的cookie中。至於這麼做的目的為何?參考以下範例:

假設某個特定用戶登入到你的網站, 當其通過身份認證之後, 便可將使用者名稱及email位址儲存至session cookie中。如此一來, 當有需要 使用這些資料時, 便可以全域變數的方式來存取這些資料, 而不需另外對資料庫作查詢。

利用下列函數, 可增加新的資料至session陣列中:

$this->session->set_userdata($array);

其中$array為一關聯式陣列, 包含所要新增的資料。以下為使用範例:

$newdata = array(
                   'username'  => 'johndoe',
                   'email'     => 'johndoe@some-site.com',
                   'logged_in' => TRUE
               );

$this->session->set_userdata($newdata);

若要一次新增一筆資料, set_userdata()亦支援下面的寫法。

$this->session->set_userdata('some_name', 'some_value');

注意: Cookie只能儲存4KB的資料, 因此使用時需注意勿超過此限制。此外若是有對資料作加密的動作, 由於 加密後會產生比原始資料長度還要長的字串, 因此更需留意儲存資料的數量。

取得所有 Session 資料

透過底下方式可以取得所有 userdata 的陣列資料:

$this->session->all_userdata()

回傳的陣列就如同底下資料:

Array
(
    [session_id] => 4a5a5dca22728fb0a84364eeb405b601
    [ip_address] => 127.0.0.1
    [user_agent] => Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_7;
    [last_activity] => 1303142623
)

刪除Session資料

如同set_userdata()可用來新增資料至session中, 使用者亦可透過傳遞session的key值給unset_userdata() 函數來刪除該筆資料。舉例來說, 若想 從session中刪除'some_name':

$this->session->unset_userdata('some_name');

除此之外, 亦可傳遞一包含欲刪項目的關聯陣列給該函數:

$array_items = array('username' => '', 'email' => '');

$this->session->unset_userdata($array_items);

快閃資料

CodeIgniter支援"快閃資料(Flashdata)", 其為一session資料, 並只對下一次的Server請求有效, 之後就自動清除。快閃資料在某些情況下 非常有用, 一般是用來提供資訊或狀態訊息等。(例如:"紀錄2已刪除")

注意:快閃資料變數名以"flash"開頭, 因此需避免在自訂的session名稱中使用此前綴。

欲新增快閃資料:

$this->session->set_flashdata('item', 'value');

如同set_userdata()的用法, 亦可傳遞一陣列給set_flashdata()。

讀取快閃資料:

$this->session->flashdata('item');

若是需要為其它的伺服器請求保留一快閃資料, 可使用keep_flashdata()函數:

$this->session->keep_flashdata('item');

將Session資料存入資料庫

基本上, session資料是以包含Session ID的陣列型態儲存在用戶的cookie裡。除非將其保存在資料庫中, 否則一般很難驗證其正確性。當然, 在一般 不那麼要求安全性, 或是對安全性要求較低的應用中, 驗證Session ID或許沒那麼重要。不過針對需較高安全性的應用, Session ID的驗證卻是必需的。Otherwise, an old session could be restored by a user modifying their cookies.

當session資料是保存在資料庫時, 每當從用戶的cookie中找到一有效的session時, 便會執行一次資料庫查詢來比對兩者的session id是否符合。若不 符合, 則該session便會被銷毀。這是因為session id只會在session建立時產生, 在這之後永遠不會有更新的動作。

為了將session儲存於資料庫中, 必須先建立一表格。以下是session類別所需的基本表格結構(適用於MySQL):

注意:該表格預設名稱為ci_sessions, 但可藉由修改application/config/config.php來設定你想要的 表格名稱。建立了資料庫表格之後, 便可以在config.php中啟動資料庫選項, 如下所示:

$config['sess_use_database'] = TRUE;

一旦啟用該選項, Session類別便會將所有的session資料存於資料庫中。

同時也要確認有在config檔中指定儲存session的表格名稱:

$config['sess_table_name'] = 'ci_sessions';

注意:Session類別內建垃圾回收機制(garbage collection), 因此使用者無須自行撰寫程式來處理相關 問題。

銷毀Session

欲清除目前的session:

$this->session->sess_destroy();

注意:此函式應該最後被呼叫, 一旦執行, 即使是flash變數也會被刪除。若只是要刪除特定變數, 使用 unset_userdata()函式。

Session參數設定

以下session相關參數可在application/config/config.php檔案中找到:

參數 預設值 選項 說明
sess_cookie_name ci_session 儲存session cookie所要使用的名稱。
sess_expiration 7200 session所要保留的時間(秒), 預設為2個小時(7200秒), 若希望session永遠有效, 將此值設為0。
sess_expire_on_close FALSE TRUE/FALSE (boolean) Whether to cause the session to expire automatically when the browser window is closed.
sess_encrypt_cookie FALSE TRUE/FALSE (布林值) 是否加密session資料。
sess_use_database FALSE TRUE/FALSE (布林值) 是否將session資料儲存於資料庫, 必須在啟用此選項前先建立一資料庫表格。
sess_table_name ci_sessions 任何有效的SQL表格名稱 session的資料庫表格名稱。
sess_time_to_update 300 以秒計時 此選項控制session類別多久重新產生一session以及新的session id。
sess_match_ip FALSE TRUE/FALSE (布林值) 是否根據對應的使用者IP來讀取session資料。需注意某些ISP會動態地改變用戶IP, 因此, 在此情況下必須將此選項設為FALSE, 以得到永久有效的session。
sess_match_useragent TRUE TRUE/FALSE (布林值) 是否根據對應的User Agent來讀取session資料。