• 博客园logo
  • 会员
  • 周边
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • YouClaw
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
百分百
http://www.qrw100.com
博客园    首页    新随笔    联系   管理    订阅  订阅

php中COOKIE与SESSION联用实现SESSION跨域

大家都知道SESSION是不可以跨域的,也就是说: A.DOMAIN.COM这个域的可执行文件不可以访问到B.DOMAIN.COM的SESSION,这个是SESSION的特性,同样也是出于安全角度才这样的.

在一般情况下,一个网站只有一个域名,www.domain.com,但是也有些网站架构是由多个子域名组建的.所以就需要SESSION可以跨子域被访问到,这样才可以实现用户的跨域登录.就是说客户在A下登录的,同样B也同时登录了,不需要用户再次登录,同时也实现了参数的跨域传递.当然不可跨域的SESSION本身已经可以帮助我们做很多事情了,那么跨域后的SESSION呢.读到这里是否很激动人心,当然你也可能是正在为SESSION跨域而发愁而找到这篇文章的,同样也祝贺你.我们长话断说了,开始Rikku的话题:COOKIE与SESSION联用实现SESSION跨域.

首先描述下我的思路,COOKIE可以指定域名,也就是说它可以跨域子域,例如:setcookie(’name’,'Rikku’,time()+3600*24,’/',’domain.com’),那么A.domain.com,B.domain.com都可以访问到$_COOKIE['name'],值也均为’Rikku’.同理,SESSION ID也可以设置成这个域名,那么A.domain.com和B.domain.com都可以得到同一个SESSION ID,那么我们的目的也就达到了.因为知道了同一个SESSION ID就可以访问到这个SESSION中的值了.SESSION有多种方式存储,文件\数据库\内存等,我们采用数据库存储,因为如果A.domain.com,B.domain.com不在同一台服务器上,那么内存和文件的存储方式就很难实现跨域了,至于到底又没有方法,Rikku还没有试过.

首先在数据库中创建一张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());
}
}

Rikku来解释下这个类:
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);

数据库链接Rikku提供大家一个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;
}


SO,上面声明对象部分你可以这样写:

$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的设置,不明白的多搜索下手册,Rikku喜欢刨根究底这样的学习方式,这样你可以学透一个知识点,而不是知道一知半解,就认为自己懂了或者会了.

最后在你需要的地方将SESSION启动:

session_start();

 

 

<?php
class session{
 private $db;
 
 function __construct($conn){
  $this->db = $conn;
  //var_dump($conn);
 }
 public function open($save_path,$session_name){
  return true;
 }
 public function close(){
  $this->db=null;
  return true;
 }
 public function read($sid){
  //var_dump($this->db);
echo  "select * from sessions where sid='".$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());
 }
 
}


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;
}


$arrPDODB=array("db_driver"=>"mysql","db_host"=>"localhost","db_name"=>"sess","db_user"=>"root","db_password"=>"root");

$session=new session(connect_db($arrPDODB));

//$a = $session->read("31e77eedb2111b63fd4120ffc9cfc6fe");
//var_dump($a);
//var_dump($session);

//var_dump($session);
//设置色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', '.219.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_start();

?>

 

posted @ 2012-01-10 17:24  爱尚美  阅读(386)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2026
浙公网安备 33010602011771号 浙ICP备2021040463号-3