PHP中利用COOKIE與SESSION聯合實現SESSION跨域

你們都知道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();
相關文章
相關標籤/搜索