你們都知道SESSION#是不能夠跨域#的,也就是說: a.demo.com這個域的可執行文件不能夠訪問到b.demo.com的SESSION,這個是SESSION的特性,一樣也是出於安全角度才這樣的.php
在通常狀況下,一個網站只有一個域名,www.demo.com,可是也有些網站架構是由多個子域名組建的.因此就須要SESSION能夠跨子域被 訪問到,這樣才能夠實現用戶的跨域登陸.就是說客戶在A下登陸的,一樣B也同時登陸了,不須要用戶再次登陸,同時也實現了參數的跨域傳遞.固然不可跨域的 SESSION自己已經能夠幫助咱們作不少事情了,那麼跨域後的SESSION呢.讀到這裏是否很激動人心,固然你也多是正在爲SESSION跨域而發 愁而找到這篇文章的,一樣也祝賀你.咱們長話斷說了,開始Ioopen的話題:COOKIE#與SESSION聯用實現SESSION跨域.數據庫
首先描述下個人思路,COOKIE能夠指定域名,也就是說它能夠跨域子域,例如:跨域
setcookie(’name’,’Ioopen’,time()+3600*24,’/’,’demo.com’)
,那麼a.demo.com,b.demo.com均可以訪問到$_COOKIE['name'],值也均爲’Ioopen’.同 理,SESSION ID也能夠設置成這個域名,那麼a.demo.com和b.demo.com均可以獲得同一個SESSION ID,那麼咱們的目的也就達到了.由於知道了同一個SESSION ID就能夠訪問到這個SESSION中的值了.SESSION有多種方式存儲,文件\數據庫\內存等,咱們採用數據庫存儲,由於若是 a.demo.com,b.demo.com不在同一臺服務器上,那麼內存和文件的存儲方式就很難實現跨域了,至於到底又沒有方法,Ioopen尚未試 過.安全
首先在數據庫中建立一張SESSION表:服務器
CREATE TABLE `sessions` ( `sid` varchar(32) NOT NULL default 」, `expiry` int(20) unsigned NOT NULL default ’0′, `value` text NOT NULL, PRIMARY KEY (`sid`), KEY `expiry` (`expiry`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8;
而後寫一個類,這個類用於讀取\插入\更新\刪除以及垃圾回收SESSIONcookie
class session{ private $db; function __construct($db){ $this->db=$db; } public function open($save_path,$session_name){ return true; } public function close(){ $this->db=null; return true; } public function read($sid){ $rs=$this->db->query(「select * from sessions where sid=’」.$sid.」‘」); foreach ($rs as $row){ return $row['value']; } return null; } public function write($sid,$value){ if(is_null($oldvalue=$this->read($sid))){ //insert return $this->db->query(」insert into sessions (sid,expiry,value)values(’」.$sid.」‘,’」.time().」‘,’」.$value.」‘)」); }else{ //update return $this->db->query(」update sessions set expiry=’」.time().」‘,value=’」.$value.」‘ where sid=’」.$sid.」‘」); } } public function destroy($sid){ return $this->db->query(」delete from sessions where sid=’」.$sid.」‘」); } public function gc($max_life_time){ return $this->db->query(’delete from sessions where expiry+’.$max_life_time.’<’.time()); } }
Ioopen來解釋下這個類:session
private $db;
類的DATABASE屬性.架構
function __construct($db)
類的構造函數,在聲明類時,能夠直接傳遞DB屬性到類中,固然若是還不明白能夠先GOOGLE一下」PHP 類 construct 方法」;dom
public function open($save_path,$session_name) //session打開,沒有什麼花頭,直接返回TRUE; public function close() //session關閉,同理open,但注意要關閉DB鏈接; public function read($sid) //session讀取,傳值SID,在數據表中將這個SID的VALUE做爲返回值返回; public function write($sid,$value)// session的寫入與更新,這個你會有疑問,爲何set expiry=’」.time().」‘,稍後答案在清空過時
SESSION GC方法中便會揭曉;函數
public function destroy($sid) //session的銷燬,很簡單,就是把數據表中等於這個SID的數據刪除掉; public function gc($max_life_time) //清空過時session,把超過max_life_time的session都銷燬掉,也就是session的建立時間加上最大生存時間小於如今時間( expiry+’.$max_life_time.’<’.time())的session數據刪除掉,這下你會明白爲何在寫入和更新session的方法中爲何寫當前時間了吧,固然這個寫法不是絕對的,隨我的意願只要你的SQL寫正確了,也就能夠了.
好咱們接着來看更重要的部分:
上面的類中須要一個數據庫連接屬性,因此聲明對象的時候須要這樣:
$session=new session(your db connect adapter);
數據庫連接Ioopen提供你們一個PDO的方法,參照使用:
function connect_db($arrPDODB){ $db=new PDO($arrPDODB['db_driver'].’:host=’.$arrPDODB['db_host'].’;dbname=’.$arrPDODB['db_name'],$arrPDODB['db_user'],$arrPDODB['db_password']); $db->query(」set names ‘utf8′」); return $db; }
所以,上面聲明對象部分你能夠這樣寫:
$session=new session(connect_db($arrPDODB));
接下來:
//設置色session id的名字 ini_set(‘session.name’, ‘sid’); //不使用 GET/POST 變量方式 ini_set(‘session.use_trans_sid’, 0); //設置垃圾回收最大生存時間 ini_set(‘session.gc_maxlifetime’, 3600); //使用 cookie 保存 session ID 的方式 ini_set(‘session.use_cookies’, 1); ini_set(‘session.cookie_path’, ‘/’); //多主機共享保存 session id 的 cookie,注意此處域名爲一級域名 ini_set(‘session.cookie_domain’, ‘*.xxx.com’); //將 session.save_handler 設置爲 user,而不是默認的 files session_module_name(‘user’); session_set_save_handler(array($session,’open’), array($session,’close’), array($session,’read’), array($session,’write’), array($session,’destroy’), array($session,’gc’));
以上都是SESSION的設置,不明白的多搜索下手冊,Ioopen喜歡刨根究底這樣的學習方式,這樣你能夠學透一個知識點,而不是知道只知其一;不知其二,就認爲本身懂了或者會了.
最後,在你須要的地方將SESSION啓動:
session_start();