近期公司項目,須要實現A域名用戶與B域名用戶的同步登陸;
該同步登錄需求需知足如下三個關鍵點:
1)A域名下登錄的用戶,跳轉到B域名下時實現同步登錄;
2)B域名下點擊A域名下的退出連接,實現A域名與B域名的同時退出
3)用戶直接訪問B域名時,能夠自動判斷A域名下是否存在用戶登陸,若是存在,則實現B域名下的用戶同步登錄。javascript
首先解決跨域的同步登錄登出,有如下可行的解決思路:
1)兩個域共享SESSION服務器,即統一的內存服務器,這樣兩個域下的SESSIONID會相同,會自動無縫實現同步登錄登出;
但該解決方案須要額外的硬件投入,而且須要懂這方面部署的技術人員
2)經過url傳遞sessionid
3)經過P3P協議獲取跨域的SESSIONphp
爲解決該需求,我通過查詢各類資料,並擬定了本身的一套解決方案,分享給你們,其要點以下:
1)當用戶在A域名下登陸後,訪問A域名下網站時,會ajax請求B域下的js腳本文件,寫入B域COOKIE及SESSION,實現B域下登陸;
2)當用戶在A域名下退出後,訪問A域名下網站時,會ajax請求B域下的js腳本文件(同登陸參數不一樣),清除B域COOKIE及SESSION,實現B域下登出;
3)當用戶直接訪問B域網頁時,請求A域下腳本,判斷A域下是否存在登陸,若是存在,則將COOKIE及SESSION賦值到當前域的網頁中,經過ajax實現當前域html
COOKIE及SESSION的寫入。java
我將baitianshi.cc設定爲A域名;bstv.cc設定爲B域名。jquery
如下是相關代碼:ajax
############# baitianshi.cc ApiController.php #################api
/* * 根據當前域(baitianshi.cc)的cookie信息設置bstv域下的cookie及session * 若是爲空,則清空處理 * */ function setckAction() { $clr = $this->_request->getParam("clr"); $bts_user = ($clr) ? '' : urlencode($_COOKIE['bts_LOGGED_USER']); $this->view->assign("bts_user",$bts_user); } /* * 提供給bstv域下,獲取當前域(baitianshi.cc)的cookie及session * 以腳本變量返回給bstv瀏覽器端 * */ function getckAction() { header('P3P: CP="CURa ADMa DEVa PSAo PSDo OUR BUS UNI PUR INT DEM STA PRE COM NAV OTC NOI DSP COR"'); echo 'var ck="'.$_COOKIE['bts_LOGGED_USER'].'";'; echo 'var sess="'.$_SESSION['user']['uid'].'";'; exit(); }
############# baitianshi.cc index.php #################
##### 默認指定index.php爲登陸返回的頁面跨域
<script src="http://www.bstv.cc/api/setck?bts_user={$bts_user}"></script>
############# bstv.cc api.php #################瀏覽器
/* * 顯示baitianshi.cc域下的cookie及SESSION * 賦值到js變量 * js 經過ajax寫入cookie和session:若是baitianshi.cc已退出,則bstv作退出處理 * */ function getbtsck() { include $this->template->getfile('api/getbtsck'); } /* * baitianshi.cc域下設置bstv域下的cookie及session * 若是爲空,則清空處理 * */ function setck() { header('P3P: CP="CURa ADMa DEVa PSAo PSDo OUR BUS UNI PUR INT DEM STA PRE COM NAV OTC NOI DSP COR"'); $bts_user = trim($_GET['bts_user']); if(!empty($bts_user)) { setcookie("bts_LOGGED_USER", urldecode($bts_user), time()+3600*24*365, "/", ".bstv.cc"); $this->cookieLoginLocal(urldecode($bts_user)); } else { setcookie("bts_LOGGED_USER", $bts_user, '-1', "/", ".bstv.cc"); unset($_SESSION['uid']); } } function setsession() { $bts_user = trim($_POST['bts_user']); if(!empty($bts_user) && empty($_SESSION['uid'])) { setcookie("bts_LOGGED_USER", urldecode($bts_user), time()+3600*24*365, "/", ".bstv.cc"); $this->cookieLoginLocal(urldecode($bts_user)); } else { echo 'uuunset'; setcookie("bts_LOGGED_USER", $bts_user, '-1', "/", ".bstv.cc"); //unset($_SESSION['uid']); } } function cookieLoginLocal($cookieId){ $cookieId = explode( '.', base64_decode($cookieId) ); if ($cookieId[0] !== 'baitianshi' || empty($cookieId[1])) { return false; } else { return $this->loginLocal($cookieId[1],false,1); } } function loginLocal($uid,$password=false,$isuid=0) { $_SESSION['uid'] = $uid; return 1; }
############# bstv.cc getbtsck.html #################服務器
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"> <head> <meta http-equiv="Content-Type" content="text/html;charset=UTF-8" /> <title>同步登錄</title> <script src="http://p.bstv.cc/js/jquery-1.8.1.min.js" type="text/javascript"></script> <script src="http://www.baitianshi.cc/api/getck"></script> <script language="javascript"> function setck(bts_user) { $.post("/api/setsession",{bts_user:bts_user},function(re){ });} setck(ck); </script> </head> <body></body> </html>
該方案尚存在的不足: 當用戶直接訪問B域時,須要加載一次該頁面後,才能判斷是否在A域登陸,並寫入當前域(B域)的SESSION