你们都知道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();