前面作了一個新項目,須要用戶資源能夠須要共享。因爲以前沒有作過這樣的東西,回家以後,立馬網站百度「單點登陸」。帖子不少,甄別以後,這裏列幾篇認爲比較有養分。javascript
http://blog.csdn.net/ghsau/article/details/20545513,http://blog.sina.com.cn/s/blog_5f66526e0102vf43.htmlphp
若是要解決兩個網站之間的同步登陸(單點登陸)問題,首先來看看一個網站的登陸問題。html
不少人知道一個網站的登陸問題,PHP不就是把經過$_SESSION['user']=array('username'=>'user1');那麼,看看php的一句代碼,作了那些操做。以windows下wamp環境配合php的配置文件php.ini看瞧瞧session的相關知識?java
php中默認提供session處理方案,能夠在php.ini配置文件中看到有這麼兩行,ajax
session.save_handler=fileredis
session.save_path = "E:/wamp/tmp",以下圖json
這兩句告訴咱們,在php中session的處理是文件files的方式,存儲的地方是E:/wamp/tmp,看看個人文件目錄下去windows
好啦,這就是傳說中的session,看得着,點得鳥。能夠用記事本打開下,能夠看到是一些字符,這是php對象數組序列化以後的字符串。就是把session對象序列化以後,寫到文件中,達到session的持久化。若是採用默認配置的話,多個網站的session文件都是存在一個地方的。也就是說,若是同一臺服務器中,有兩個網站,網站a和網站b的session文件都會存儲在一個地方,session文件都有本身的惟一標示符,sessionID。sessionID的生成,sessionID是惟一的,這個sessionID跟session的持久化文件名稱是對應的。php經過sessionID去獲取session文件,反序列化出來,就能達到session讀取的功能了。這樣的話,會不會想到,若是兩個sessionID相同的話,用戶在網站a登陸了,用戶在去訪問網站b的時候,若是sessionID相同,就是已經的登陸的狀態了。數組
解決:兩個網站sessionID相同思路瀏覽器
php提供了session_id()這個函數能夠獲取到sessionID,能夠設置sessionID。在原生PHP中,能實現經過session_id()去修改sessionID,在一些框架中比較難實現,須要深究框架代碼,爲什麼難實現呢,這裏要了解session_id()和session_start()一些關聯了,須要先設定sessionID以後,再去session_start()。因此在框架中,會自動的啓用session_start(),因此在啓動以後再去修改,sessionID未被修改。
sessionID相同的還有一種方式,就是瀏覽器修改sessionID,sessionID是存儲在cookie中,在配置文件中,能夠看到session.name = PHPSESSID,那麼這個PHPSESSID就是sessionID在cookie中的name了。以下圖
瀏覽器和服務器之間每次交互,這個cookie值都會傳遞給服務器,因此若是咱們前臺去修改這個值的話,就可讓兩個網站公用一個sessionID的值了。
具體實施:在網站b全部的頁面用戶加載的時候,去請求網站a的一個接口,看看用戶是否有登陸,若是有的話,就放回sessionID給網站b,網站b接受到sessionID以後,就修改瀏覽器cookie中的PHPSESSID值。這樣網站b的用戶再去操做的話,就會發現本身sessionID對應的session文件跟網站a是同一個,從而達到同步登陸。
網站b代碼須要作的就是頁面每次訪問都須要去請求a網站的數據判斷用戶是否在a網站登陸。
<if condition="!session('?member')"> <!--未登陸--> <script type="text/javascript"> function setCookie(name,value) { document.cookie = name + "="+ escape (value)+";path=/"; } //jsonp登陸函數 function jsonp_do(data) { //log(''); } <{~$t=time()}> $(document).ready(function(){ $.ajax({ type:'get', url:"<{:C('SSO_Site')}>?_ts=<{$t}>&_token=<{:md5($t.C('SecretKey'))}>", dataType:'jsonp', crossDomain: true, jsonp: "callback", jsonpCallback:'jsonp_do', success:function(data){ if(data.error==0){ setCookie('PHPSESSID',data.sess_id); } }, error: function(XHR, textStatus, errorThrown){ //log } }); }); </script> </if>
那麼網站a就要給出對應的頁面來給網站b請求且返回數據。
/** * [index 用戶登陸] * @Author:wty * @DateTime:2016年12月12日11:22:02 * @return [type] [description] */ public function index() { //能夠適當加入用戶ip做爲加密因子和瀏覽器因數 $token=I('get._token');//加密串 $timespan=I('get._ts');//時間時間戳 $referer=$_SERVER['HTTP_REFERER'];//這裏能夠限定安全網址 $error=100; //這裏須要配置 $allow=C('Allow_Site'); if(in_array($referer,$allow)){//若是是在容許訪問列表裏面 $error=1; if($token&&$timespan){ $error=2; $secretKey=C('SecretKey');//祕鑰 $check=md5($timespan.$secretKey); if($check==$token){ $error=3; if(session('?member')){ $error=0; $return=array('error'=>0,'username'=>session('member.username'),'sess_id'=>session_id()); echo 'jsonp_do('.json_encode($return).')'; exit; } } } } echo 'jsonp_do('.json_encode(array('error'=>$error)).')'; }
如今多數網站都會採用到負載均衡多服務器,若是是多服務器的話,session的存儲能夠考慮的memcached或者redis中,上面說道php對於session的默認存儲方式是files,若是用memcached的話,就要修改配置文件php.ini
session.save_handler=memcached
session.save_path = "tpc://192.168.1.1"
在save_handler=memcached或者memcache這裏,有點區別,若是配置寫的是memcached的話,下面的save_path就要寫tcp://192.168.1.1:11211,若是是memcache的話,save_path就要填寫爲192.168.1.1:11211
差異不大。
至此簡單版本的單點登陸基本完成了。
更多原創博客請看我的獨立博客:傳送門