前言
前陣子的在開發的時候,有一項是要在登入頁做remeber me的功能
這其實還滿簡單的,畢竟只要有買過php的書幾乎都會有範例
不同的是之前是純粹用PHP寫,現在用的是CI
以前沒有用過CI提供的cookie存取功能,但有看過config檔裡面有相關的設定
/* |-------------------------------------------------------------------------- | Cookie Related Variables |-------------------------------------------------------------------------- | | 'cookie_prefix' = Set a prefix if you need to avoid collisions | 'cookie_domain' = Set to .your-domain.com for site-wide cookies | 'cookie_path' = Typically will be a forward slash | 'cookie_secure' = Cookies will only be set if a secure HTTPS connection exists. | */ $config['cookie_prefix'] = "c_"; $config['cookie_domain'] = $_SERVER['HTTP_HOST']; $config['cookie_path'] = "/"; $config['cookie_secure'] = TRUE;
所以就先設定了一下,但我當下沒有發現自己犯了一個錯…(官方的說明文件也沒有寫得很清楚,還是看code最準XD)
把remeber me功能的做完的時候,當下測試的時候發現登入功能GG了(…WTF)
一開始是馬上去看我剛剛寫的程式是不是有BUG,但還真的沒有啊…
神奇的是我把剛剛寫的code刪光光,登入功能依然GG…
所以我就開始想想我寫code之前做了什麼事?
config~我改了config,但我只是設定cookie相關的config而已
也沒有更動到session的東西啊….
秉持著爬source code的精神,終於讓我釐清事情的來龍去脈…容我慢慢道來
文件vs註解
我在改config相關的cookie設定前有先去看官方的說明文件
其中有一項是設定$config[‘cookie_secure’]
文件是這樣寫的:
The secure boolean is only needed if you want to make it a secure cookie by setting it to TRUE.
所以我就把cookie_secure設為TRUE <—(這就是我犯的錯誤)
但後來在檢查config.php的時候我發現它的註解的解釋是:
/* | 'cookie_secure' = Cookies will only be set if a secure HTTPS connection exists. */
所以,如果將CI config.php的cookie_secure的參數設為TRUE
代表利用$this->input->set_cookie()設定的cookie只能透過https的方式傳輸!
但我做的那個網站並沒有用https…這就是最根本的問題 (如果官方的文件和助解一樣的話我應該就不會把cookie_secure設成TRUE了)
還有還有
debug到這邊應該就可以告一個段落了~~
但是!!我還是沒搞懂為何cookie_secure設為TRUE之後,我TMD的就不能登入
基於爬爬source code的精神,發現..在/system/libraries/Session.php有一段程式碼解決了我最後一個疑惑:
// Fetch the cookie $session = $this->CI->input->cookie($this->sess_cookie_name); // No cookie? Goodbye cruel world!... if ($session === FALSE) { log_message('debug', 'A session cookie was not found.'); return FALSE; } // Decrypt the cookie data if ($this->sess_encrypt_cookie == TRUE) { $session = $this->CI->encrypt->decode($session); } else { // encryption was not used, so we need to check the md5 hash $hash = substr($session, strlen($session)-32); // get last 32 chars $session = substr($session, 0, strlen($session)-32); // Does the md5 hash match? This is to prevent manipulation of session data in userspace if ($hash !== md5($session.$this->encryption_key)) { log_message('error', 'The session cookie data did not match what was expected. This could be a possible hacking attempt.'); $this->sess_destroy(); return FALSE; } }
CI在讀取seesion的時候會有一個檢查機制
1.先檢查Server上的session和client端cookie裡面加密後的session是否存在
2.檢查是否為加密的值
3.比對seesion和cookie是否match
總結因果
1.目前開發的網站不是走HTTPS
2.把config.php的cookie_secure的參數設為TRUE
3.帳密都輸入正確時,程式存一個seesion在Server上,CI則自動在cookie端存一個加密後的session值
4.轉跳到登入後的頁面時,會檢查是否有登入,但這個機制觸發了..
5.CI在讀取seesion時會去比對seesion和cookie是否match
6.但無法取得這個cookie的值…所以return FALSE…死在
log_message('debug', 'A session cookie was not found.');