大家都知道SESSION是不可以跨域的,也就是说:A.WEMVC.COM这个域的可执行文件不可以访问到B.******************.COM的SESSION,这个是SESSION的特性,同样也是出于
安全角度才这样的.
在一般情况下,一个网站只有一个域名,但是也有些网站架构是由多个子域名组建的.所以就需要SESSION可以跨子域被访问到,这样才可以实现用户的跨域登录.就是说客户在A下登录的,同样B也同时登录了,不需要用户再次登录,同时也实现了参数的跨域传递.当然不可跨域的SESSION本身已经可以帮助我们做很多事情了,那么跨域后的SESSION呢.读到这里是否很激动人心,当然你也可能是正在为SESSION跨域而发愁而找到这篇文章的,同样也祝贺你.我们长话断说了,开始我们今天的课程:COOKIE与SESSION联用实现SESSION跨域.
首先让我们再重新温习下
PHP中的COOKIE和SESSION:
COOKIE:
定义:
cookie常用于识别用户
。cookie是
服务器留在用户计算机中的小文件
。每当相同的计算机通过浏览器请求页面时
,它同时会发送cookie。通过
PHP,您能够创建并取回cookie的值。PS:其中文名叫”曲奇”.
在PHP中用setCookie函数来设置COOKIE,该函数一共有7个参数(在此我要向曾经我面试过的一位同仁道歉,当时我把答案说成了6个,SORRY~,同时我也提醒广大作家尽快更新自己的文章,在PHP5.2.0版本中已经增加为7个参数.),这7个参数分别为string$name[,string$value[,int$expire[,string$path[,string$domain[,bool$secure[,bool$httponly]]]]]].
nameThenameofthecookie.规定cookie的名称。
valueThevalueofthecookie.Thisvalueisstoredontheclientscomputer;donotstoresensitiveinformation.Assumingthenameis‘cookiename’,thisvalueisretrievedthrough$_COOKIE['cookiename']规定cookie的值。
expireThetimethecookieexpires.ThisisaUnixtimestampsoisinnumberofsecondssincetheepoch.Inotherwords,you’llmostlikelysetthiswiththetime()functionplusthenumberofsecondsbeforeyouwantittoexpire.Oryoumightusemktime().time()+60*60*24*30willsetthecookietoexpirein30days.Ifsetto0,oromitted,thecookiewillexpireattheendofthesession(whenthebrowsercloses).规定cookie的有效期。
Note:YoumaynoticetheexpireparametertakesonaUnixtimestamp,asopposedtothedateformatWdy,DD-Mon-YYYYHH:MM:SSGMT,thisisbecausePHPdoesthisconversioninternally.
expireiscomparedtotheclient’stimewhichcandifferfromserver’stime.
pathThepathontheserverinwhichthecookiewillbeavailableon.Ifsetto‘/’,thecookiewillbeavailablewithintheentiredomain.Ifsetto‘/foo/’,thecookiewillonlybeavailablewithinthe/foo/directoryandallsub-directoriessuchas/foo/bar/ofdomain.Thedefaultvalueisthecurrentdirectorythatthecookieisbeingsetin.规定cookie的
服务器路径。
domainThedomainthatthecookieisavailable.Tomakethecookieavailableonallsubdomainsofexample.comthenyou’dsetitto‘.example.com’.The.isnotrequiredbutmakesitcompatiblewithmorebrowsers.Settingittowww.example.comwillmakethecookieonlyavailableinthewwwsubdomain.Refertotailmatchinginthe»specfordetails.规定cookie的域名。
secureIndicatesthatthecookieshouldonlybetransmittedoverasecureHTTPSconnectionfromtheclient.WhensettoTRUE,thecookiewillonlybesetifasecureconnectionexists.ThedefaultisFALSE.Ontheserver-side,it’sontheprogrammertosendthiskindofcookieonlyonsecureconnection(e.g.withrespectto$_SERVER["HTTPS"]).规定是否通过
安全的HTTPS连接来传输cookie。
httponlyWhenTRUEthecookiewillbemadeaccessibleonlythroughtheHTTPprotocol.Thismeansthatthecookiewon’tbeaccessiblebyscriptinglanguages,suchasJavaScript.ThissettingcaneffectlyhelptoreduceidentitytheftthroughXSSattacks(althoughitisnotsupportedbyallbrowsers).AddedinPHP5.2.0.TRUEorFALSE.规定是否必须通过HTTP协议来定义访问COOKIE,防止XSS攻击.
SESSION全面教程
SESSION在这里就不过多的讲解了,主要是:
session_cache_expire—Returncurrentcacheexpire
session_cache_limiter—Getand/orsetthecurrentcachelimiter
session_commit—Aliasofsession_write_close
session_decode—Decodessessiondatafromastring
session_destroy—Destroysalldataregisteredtoasession
session_encode—Encodesthecurrentsessiondataasastring
session_get_cookie_params—Getthesessioncookieparameters
session_id—Getand/orsetthecurrentsessionid
session_is_registered—Findoutwhetheraglobalvariableisregisteredinasession
session_module_name—Getand/orsetthecurrentsessionmodule
session_name—Getand/orsetthecurrentsessionname
session_regenerate_id—Updatethecurrentsessionidwithanewlygeneratedone
session_register—Registeroneormoreglobalvariableswiththecurrentsession
session_save_path—Getand/orsetthecurrentsessionsavepath
session_set_cookie_params—Setthesessioncookieparameters
session_set_save_handler—Setsuser-levelsessionstoragefunctions
session_start—Initializesessiondata
session_unregister—Unregisteraglobalvariablefromthecurrentsession
session_unset—Freeallsessionvariables
session_write_close—Writesessiondataandendsession
哈哈,不是我懒噢,这里只讲跨域.
OK,大概温习了下COOKIE和SESSION,开始实现我们的跨域.
首先我描述下我的思路,COOKIE可以指定域名,也就是说它可以跨域子域,例如:setcookie(’name’,'joshua’,time()+3600*24,’/',’wemvc.com’),那么A.wemvc.com,B.wemvc.com都可以访问到$_COOKIE['name'],值也均为’joshua’.同理,SESSIONID也可以设置成这个域名,那么A.wemvc.com和B.wemvc.com都可以得到同一个SESSIONID,那么我们的目的也就达到了.因为知道了同一个SESSIONID就可以访问到这个SESSION中的值了.SESSION有多种方式存储,文件数据库内存等,我们采用数据库存储,因为如果A.wemvc.com,B.wemvc.com不在同一台服务器上,那么内存和文件的存储方式就很难实现跨域了,至于到底又没有方法,本人还没有试过.
首先在数据库中创建一张SESSION表:
CREATETABLE`sessions`(
`sid`varchar(32)NOTNULLdefault'',
`expiry`int(20)unsignedNOTNULLdefault'0',
`value`textNOTNULL,
PRIMARYKEY(`sid`),
KEY`expiry`(`expiry`)
)ENGINE=MyISAMDEFAULTCHARSET=utf8;
然后写一个类,这个类用于读取插入更新删除以及垃圾回收SESSION
classsession{
private$db;
function__construct($db){
$this->db=$db;
}
publicfunctionopen($save_path,$session_name){
returntrue;
}
publicfunctionclose(){
$this->db=null;
returntrue;
}
publicfunctionread($sid){
$rs=$this->db->query("select*fromsessionswheresid='".$sid."'");
foreach($rsas$row){
return$row['value'];
}
returnnull;
}
publicfunctionwrite($sid,$value){
if(is_null($oldvalue=$this->read($sid))){
//insert
return$this->db->query(”insertintosessions(sid,expiry,value)values(’”.$sid.”‘,’”.time().”‘,’”.$value.”‘)”);
}else{
//update
return$this->db->query(”updatesessionssetexpiry=’”.time().”‘,value=’”.$value.”‘wheresid=’”.$sid.”‘”);
}
}
publicfunctiondestroy($sid){
return$this->db->query(”deletefromsessionswheresid=’”.$sid.”‘”);
}
publicfunctiongc($max_life_time){
return$this->db->query(’deletefromsessionswhereexpiry+’.$max_life_time.’<’.time());
}
}
我来解释下这个类:
private$db;类的DATABASE属性.
function__construct($db)类的构造函数,在声明类时,可以直接传递DB属性到类中,当然如果还不明白可以先GOOGLE一下”PHP类construct方法”;
publicfunctionopen($save_path,$session_name)session打开,没有什么花头,直接返回TRUE;
publicfunctionclose()session关闭,同理open,但注意要关闭DB连接;
publicfunctionread($sid)session读取,传值SID,在数据表中将这个SID的VALUE作为返回值返回;
publicfunctionwrite($sid,$value)session的写入与更新,这个你会有疑问,为什么setexpiry=’”.time().”‘,稍后答案在清空过期SESSIONGC方法中便会揭晓;
publicfunctiondestroy($sid)session的销毁,很简单,就是把数据表中等于这个SID的数据删除掉;
publicfunctiongc($max_life_time)清空过期session,把超过max_life_time的SESSION都销毁掉,也就是SESSION的创建时间加上最大生存时间小于现在时间(expiry+’.$max_life_time.’<’.time())的SESSION数据删除掉,这下你会明白为什么在写入和更新SESSION的方法中为什么写当前时间了吧,当然这个写法不是绝对的,随个人意愿只要你的
SQL写正确了,也就可以了.
好我们接着来看更重要的部分:
上面的类中需要一个数据库链接属性,所以声明对象的时候需要这样:
$session=newsession(yourdbconnectadapter);
数据库链接我可以提供大家一个PDO的方法,参照使用:
functionconnect_db($arrPDODB){
$db=newPDO($arrPDODB['db_driver'].’:host=’.$arrPDODB['db_host'].’;dbname=’.$arrPDODB['db_name'],$arrPDODB['db_user'],$arrPDODB['db_password']);
$db->query(”setnames‘utf8′”);
return$db;
}
SO,上面声明对象部分你可以这样写:
$session=newsession(connect_db($arrPDODB));
接下来:
//设置色sessionid的名字
ini_set('session.name','sid');
//不使用GET/POST变量方式
ini_set('session.use_trans_sid',0);
//设置垃圾回收最大生存时间
ini_set('session.gc_maxlifetime',3600);
//使用COOKIE保存SESSIONID的方式
ini_set('session.use_cookies',1);
ini_set('session.cookie_path','/');
//多主机共享保存SESSIONID的COOKIE,注意此处域名为一级域名
ini_set('session.cookie_domain','wemvc.com');
//将session.save_handler设置为user,而不是默认的files