php實現SESSION跨域

稍微大一點的網站,通常都會有不只一個服務器,每個服務器運行着不同的功能模塊或者不同的子系統,他們使用不同的二級域名,比如www.a.com、i.a.com、bbs.a.com。而一個整體性強的網站,用戶系統是統一的,即一套用戶名、密碼在整個網站的各個子系統中都是可以登錄使用的。各個服務器共享用戶數據是比較容易實現的,只需要在後端放個數據庫服務器,各個服務器通過統一接口對用戶數據進行訪問即可。但還存在一個問題,就是用戶在i.a.com登錄之後,進入www.a.com時,仍然需要重新登錄,基本的通行證的問題,映射到技術上,其實就是各個服務器之間如何實現共享 SESSION 數據的問題。

爲了解決這個問題,我們採用將 SESSION 的數據保存數據庫的方式。關於PHP SESSION的掃盲這裏就不在累贅。在默認情況下,各個服務器會各自分別對同一個客戶端產生 SESSION ID,如對於同一個用戶瀏覽器,www.a.com系統產生的 SESSION ID 是a0211e9de3192ba6c22992d27a1b6a0a,而i.a.com生成的則是277003f262f0c366946a86a28ba431d8。另外,PHP 的 SESSION 數據都是分別保存在本服務器的文件系統中。

想要共享 SESSION 數據,那就必須實現兩個目標:www.a.com和i.a.com所產生的SESSION ID相同,並且可通過同一個 COOKIE 進行傳遞,也就是說各個服務器必須可以讀取同一個名爲 PHPSESSID 的 COOKIE;另一個是 SESSION 數據必須存放在一個各個系統都能訪問到的地方。簡單地說就是多服務器共享客戶端的 SESSION ID,同時還必須共享服務器端的 SESSION 數據。

第一個目標的實現其實很簡單,只需要對 COOKIE 的域(domain)進行特殊地設置即可,默認情況下,COOKIE 的域是當前服務器的域名/IP 地址,而域不同的話,各個服務器所設置的 COOKIE 是不能相互訪問的,如 www.a.com 的服務器是不能讀寫 www.b.com 服務器設置的 COOKIE 的。這裏我們所說的同一網站的服務器有其特殊性,那就是他們同屬於同一個一級域,如:www.a.com 和 i.a.com 都屬於域 .a.com,那麼我們就可以設置 COOKIE 的域爲 .a.com,這樣 www.a.com、i.aaa.com 等等都可以訪問此 COOKIE。PHP 代碼中的設置方法如下:

1 ini_set('session.cookie_domain''.a.com');

這樣各個系統共享同一客戶端 SESSION ID 的目的就達到了,下面就是共享SESSION數據,我們就將SESSION數據放在數據庫中,首先建立數據庫表:

1 CREATE TABLE sessions (
2  session_id varchar(32) NOT NULL,
3  session_last_access int(10) unsigned,
4  session_data text,
5  PRIMARY KEY (session_id)

session_id爲主鍵,保存SESSION ID ,session_last_access是SESSION最後更新時間,session_data是SESSION數據。
PHP 提供了session_set_save_handle() 函數,可以用此函數自定義 SESSION 的處理過程,當然首先要先將 session.save_handler 改成 user,可在 PHP 中進行設置:
接下來着重講一下 session_set_save_handle() 函數,此函數有六個參數:
session_set_save_handler ( string open, string close, string read, string write, string destroy, string gc )
各個參數爲各項操作的函數名,這些操作依次是:打開、關閉、讀取、寫入、銷燬、垃圾回收。PHP 手冊中有詳細的例子,詳細代碼如下:

01 $gb_DBHOSTname "127.0.0.1"//主機的名稱或是IP地址
02 $gb_DBname "dbname"//數據庫名稱
03 $gb_DBuser "username"//數據庫用戶名稱
04 $gb_DBpass "pwd"//數據庫密碼
05 $gb_COOKIE_DOMAIN '.a.com';
06 $SESS_DBH "";
07 $SESS_LIFE = get_cfg_var("session.gc_maxlifetime"); //得到session的最大有效期。
08  session_id(); //不使用 GET/POST 變量方式
09 ini_set('session.use_trans_sid', 0); //設置垃圾回收最大生存時間
10 ini_set('session.gc_maxlifetime', 13600); //使用 COOKIE 保存 SESSION ID 的方式
11 ini_set('session.use_cookies', 1);
12 ini_set('session.cookie_path''/'); //多主機共享保存 SESSION ID 的 COOKIE
13 ini_set("session.cookie_domain"$gb_COOKIE_DOMAIN);
14 //將 session.save_handler 設置爲 user,而不是默認的 files session_module_name('user');
15 function sess_open($save_path$session_name) {
16     global $gb_DBHOSTname$gb_DBname$gb_DBuser$gb_DBpass$SESS_DBH;
17     if (!$SESS_DBH = mysql_pconnect($gb_DBHOSTname$gb_DBuser$gb_DBpass)) {
18         die('MySQL Error');
19     }
20     mysql_query("SET character_set_connection=utf8, character_set_results=utf8, character_set_client=binary"$SESS_DBH);
21     if (!mysql_select_db($gb_DBname$SESS_DBH)) {
22         die('MySQL Error');
23     }
24     return true;
25 }
26  
27 function sess_close() {
28     global $SESS_DBH;
29     //$SESS_DBH->Close();
30     return true;
31 }
32  
33 function sess_read($key) {
34     global $SESS_DBH$SESS_LIFE;
35 //      var_dump($SESS_DBH);
36     $qry "select session_data from sessions where session_id = '$key' ";
37     $qid = mysql_query($qry$SESS_DBH);
38 //      var_dump($qid);
39     if (list ($value) = mysql_fetch_row($qid)) {
40         return $value;
41     }
42     return false;
43 }
44  
45 function sess_write($key$val) {
46     global $SESS_DBH$SESS_LIFE;
47     $session_last_access = time();
48     $value $val;
49     $qry "insert into  sessions values('$key',$session_last_access,'$value')";
50     $qid = mysql_query($qry$SESS_DBH);
51     if (!$qid) {
52         $qry "update sessions set session_last_access=$session_last_access, session_data='$value' where session_id='$key' ";
53         $qid = mysql_query($qry$SESS_DBH);
54     }
55     return $qid;
56 }
57  
58 function sess_destroy($key) {
59     global $SESS_DBH;
60     $qry "delete from sessions where session_id = '$key'";
61     $qid = mysql_query($qry$SESS_DBH);
62     return $qid;
63 }
64  
65 function sess_gc($maxlifetime) {
66     global $SESS_DBH;
67     $old = time() - $maxlifetime;
68     $old = mysql_real_escape_string($old);
69     $qry "delete from sessions where session_last_access < " $old;
70     $qid = mysql_query($qry$SESS_DBH);
71     return mysql_affected_rows($SESS_DBH);
72 }
73 session_module_name();
74 session_set_save_handler("sess_open""sess_close""sess_read""sess_write","sess_destroy""sess_gc");
75 session_start();
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章