大家都知道SESSION是不可以跨域的,也就是說: A.WEMVC.COM這個域的可執行文件不可以訪問到B.WEMVC.COM的SESSION,這個是SESSION的特性,同樣也是出于安全角度才這樣的. 在一般情況下,一個網站只有一個域名,但是也有些網站架構是由多個子域名組建的.所以就需要SESSION可以跨子域被訪問到,這樣才可以實現用戶的跨域登錄.就是說客戶在A下登錄的,同樣B也同時登錄了,不需要用戶再次登錄,同時也實現了參數的跨域傳遞.當然不可跨域的SESSION本身已經可以幫助我們做很多事情了,那么跨域后的SESSION呢.讀到這里是否很激動人心,當然你也可能是正在為SESSION跨域而發愁而找到這篇文章的,同樣也祝賀你.我們長話斷說了,開始我們今天的課程:COOKIE與SESSION聯用實現SESSION跨域.首先讓我們再重新溫習下PHP中的COOKIE和SESSION:COOKIE: 定義: cookie 常用于識別用戶。cookie 是服務器留在用戶計算機中的小文件。每當相同的計算機通過瀏覽器請求頁面時,它同時會發送 cookie。通過 PHP,您能夠創建并取回 cookie 的值。PS:其中文名叫 曲奇 . 在PHP中用sethtml' target='_blank'>Cookie函數來設置COOKIE,該函數一共有7個參數(在此我要向曾經我面試過的一位同仁道歉,當時我把答案說成了6個,SORRY~,同時我也提醒廣大作家盡快更新自己的文章,在PHP5.2.0版本中已經增加為7個參數.),這7個參數分別為 string $name [, string $value [, int $expire [, string $path [, string $domain [, bool $secure [, bool $httponly ]]]]]] . name The name of the cookie. 規定 cookie 的名稱。 value The value of the cookie. This value is stored on the clients computer; do not store sensitive information. Assuming the name is cookiename , this value is retrieved through $_COOKIE['cookiename'] 規定 cookie 的值。 expire The time the cookie expires. This is a Unix timestamp so is in number of seconds since the epoch. In other words, you ll most likely set this with the time() function plus the number of seconds before you want it to expire. Or you might use mktime(). time()+60*60*24*30 will set the cookie to expire in 30 days. If set to 0, or omitted, the cookie will expire at the end of the session (when the browser closes).規定 cookie 的有效期。Note: You may notice the expire parameter takes on a Unix timestamp, as opposed to the date format Wdy, DD-Mon-YYYY HH:MM:SS GMT, this is because PHP does this conversion internally. expire is compared to the client s time which can differ from server s time. path The path on the server in which the cookie will be available on. If set to / , the cookie will be available within the entire domain . If set to /foo/ , the cookie will only be available within the /foo/ directory and all sub-directories such as /foo/bar/ of domain . The default value is the current directory that the cookie is being set in.規定 cookie 的服務器路徑。 domain The domain that the cookie is available. To make the cookie available on all subdomains of example.com then you d set it to .example.com . The . is not required but makes it compatible with more browsers. Setting it to www.example.com will make the cookie only available in the www subdomain. Refer to tail matching in the spec for details.規定 cookie 的域名。 secure Indicates that the cookie should only be transmitted over a secure HTTPS connection from the client. When set to TRUE, the cookie will only be set if a secure connection exists. The default is FALSE. On the server-side, it s on the programmer to send this kind of cookie only on secure connection (e.g. with respect to $_SERVER[ HTTPS ]).規定是否通過安全的 HTTPS 連接來傳輸 cookie。 httponly When TRUE the cookie will be made accessible only through the HTTP protocol. This means that the cookie won t be accessible by scripting languages, such as JavaScript. This setting can effectly help to reduce identity theft through XSS attacks (although it is not supported by all browsers). Added in PHP 5.2.0. TRUE or FALSE.規定是否必須通過HTTP協議來定義訪問COOKIE,防止XSS攻擊. SESSION全面教程 SESSION在這里就不過多的講解了,主要是: session_cache_expire Return current cache expire session_cache_limiter Get and/or set the current cache limiter session_commit Alias of session_write_close session_decode Decodes session data from a string session_destroy Destroys all data registered to a session session_encode Encodes the current session data as a string session_get_cookie_params Get the session cookie parameters session_id Get and/or set the current session id session_is_registered Find out whether a global variable is registered in a session session_module_name Get and/or set the current session module session_name Get and/or set the current session name session_regenerate_id Update the current session id with a newly generated one session_register Register one or more global variables with the current session session_save_path Get and/or set the current session save path session_set_cookie_params Set the session cookie parameters session_set_save_handler Sets user-level session storage functions session_start Initialize session data session_unregister Unregister a global variable from the current session session_unset Free all session variables session_write_close Write session data and end session 哈哈,不是我懶噢,這里只講跨域. OK,大概溫習了下COOKIE和SESSION,開始實現我們的跨域. 首先我描述下我的思路,COOKIE可以指定域名,也就是說它可以跨域子域,例如:setcookie( name ,'joshua ,time()+3600*24, /', wemvc.com ),那么A.wemvc.com,B.wemvc.com都可以訪問到$_COOKIE['name'],值也均為 joshua .同理,SESSION ID也可以設置成這個域名,那么A.wemvc.com和B.wemvc.com都可以得到同一個SESSION ID,那么我們的目的也就達到了.因為知道了同一個SESSION ID就可以訪問到這個SESSION中的值了.SESSION有多種方式存儲,文件/數據庫/內存等,我們采用數據庫存儲,因為如果A.wemvc.com,B.wemvc.com不在同一臺服務器上,那么內存和文件的存儲方式就很難實現跨域了,至于到底又沒有方法,本人還沒有試過. 首先在數據庫中創建一張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;
然后寫一個類,這個類用于讀取/插入/更新/刪除以及垃圾回收SESSION 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()); } } 我來解釋下這個類: private $db; 類的DATABASE屬性. function __construct($db) 類的構造函數,在聲明類時,可以直接傳遞DB屬性到類中,當然如果還不明白可以先GOOGLE一下 PHP 類 construct 方法 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); 數據庫鏈接我可以提供大家一個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; }