PHP中,如果要獲取SESSION數據,必須要有對應的session_id,session_id的獲取方式有兩種
1.基於客戶端的cookie
2.基於url
先說第一種情況,基於客戶端的cookie.服務器端的腳本在開啟session后,會依據php.ini來存儲session,下面列舉一些
session.save_handler 定義存儲和獲取與會話關聯的數據的處理器的名字。默認為 files。如果設定為files(session.save_handler = files),則采用的是php內置機制,如果想自定義存儲方式(比如存儲到數據庫中),則使用session_set_save_handler()進行自定義設置
session.save_path 定義了傳遞給存儲處理器的參數(注釋1)。如果選擇了默認的 files 文件處理器,則此值是創建文件的路徑。默認為 /tmp,也可以修改,比如session.save_path = "e:/wamp/tmp"。也可以使用session_save_path()在腳本中設定(一定在session_start前設定)
舉例
假設腳本是session.php
session_save_path(getcwd()."/session_folder");//為方便我已經創建好session_folder這個目錄 session_start(); $_SESSION['aa']='bb'; $_SESSION['cc']='dd';
運行完畢,查看session_folder目錄
如果一個服務器上有多個項目,那么每個項目設定不同的session_save_path是有必要的,因為PHP會根據session的的垃圾回收機制,來清理默認session目錄下的session文件:項目A的php腳本在運行時,極有可能刪掉項目B的php腳本生成的session文件.所以,每個項目采用不同的session路徑,並在session_start()前,就指定session路徑,就互不干擾了.
看這個session文件的名字,其中sess_后面的一大串就是session_id,可以用session_id()設置/讀取;
打開這個文件,看一下
aa|s:2:"bb";cc|s:2:"dd";
這是session的序列化處理器序列化的數據,默認值是php(session.serialize_handler = php),
瀏覽器請求這個文件后,服務器會返回這樣的響應頭
response header
Cache-Control:no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Connection:Keep-Alive
Content-Length:0
Content-Type:text/html; charset=utf-8
Date:Fri, 18 Nov 2016 14:55:24 GMT
Expires:Thu, 19 Nov 1981 08:52:00 GMT
Keep-Alive:timeout=5, max=100
Pragma:no-cache
Server:Apache/2.4.9 (Win32) PHP/5.5.12
Set-Cookie:PHPSESSID=193tha35k5fj547nbj6o108as3; path=/
X-Powered-By:PHP/5.5.12
黃色部分就是服務器返回的cookie
這個cookie是php生成的,
名:PHPSESSD;
這個PHPSESSID是會話名,是在php.ini中設定:session.name = PHPSESSID,也可以使用session_name()來讀取/設定
值:193tha35k5fj547nbj6o108as3;
這個id值就是存儲在服務器端的文件的名字啦
路徑:/
路徑也是php.ini中設定:session.cookie_path = / ,也可以session_set_cookie_params() 設定或session_get_cookie_params()讀取.
另外,查看這個cookie的生命周期,偷懶我就直接看瀏覽器了
可以看到過期時間是關閉瀏覽器的時候
這個值是php.ini中session.cookie_lifetime設定的(session.cookie_lifetime = 0), 以秒數指定了發送到瀏覽器的 cookie 的生命周期。值為 0 表示“直到關閉瀏覽器”。默認為 0。也可用 session_get_cookie_params()讀取或session_set_cookie_params() 設定
另外,我再次訪問session.php,使用js讀取cookie
這么重要的數據,js竟然讀取到了,萬一被XSS攻擊了怎么辦,不行,這個cookie不能被js獲取,要設定一下
php.ini中,session.cookie_httponly=on,這樣js就不會獲取到啦
如果用戶的瀏覽器禁用cookie怎么辦?
如果禁用了cookie,而php又沒有進行額外設置,則php無法讀取cookie,也無法獲取session值,因為php.ini中默認是這樣設定的:
session.use_only_cookies = 1,意思是說,php只能根據cookie中的PHPSESSID的值來存入/獲取/修改會話id,這樣做是相對安全的,也是php推薦的,因而在此設定值下,如果禁用了cookie,就獲取不到session啦
可是,我就是想在禁用cookie的情況下也要設定/讀取session值怎么辦?php也是允許的,這就是session的第二種獲取方式,就是基於URL
php.ini有個選項值:session.use_trans_sid,
設置session.use_trans_sid=on,就可以基於URL來傳遞會話id,比如我設定session時把session_id()存儲在一個隱藏域中,
<input type="hidden" name="<?php echo session_name() ?> value=<?php echo session_id() ?>>
再次訪問是,我就可以使用諸如http://php.com/session.php?PHPSESSID=p7iqqncndjmf13si9r6bafg1h1的URL,這樣就可以獲取session了,但這是很不安全的,極力不推薦.因為url被竊取就完蛋了.
使用這個配置項有個前提,就是session.use_only_cookies = 0
注釋1
即session_set_save_handler()中指定的處理器的參數,處理器的一種方法按手冊是這樣設置
session_set_save_handler ( callable $open
, callable $close
, callable $read
, callable $write
, callable $destroy
, callable $gc
[, callable $create_sid
] ),
其中的第一個方法open(string $savePath, string $sessionName),$savepath就是根據session.save_path的值來獲得的
以上絕大部分都是摘自手冊,大家可以去看手冊,更詳細,尤其是會話安全方面,更要注意.