SSO單點登錄PHP簡單版


  前面做了一個新項目,需要用戶資源可以需要共享。由於之前沒有做過這樣的東西,回家之后,立馬網站百度“單點登錄”。帖子很多,甄別之后,這里列幾篇認為比較有營養。

  http://blog.csdn.net/ghsau/article/details/20545513,http://blog.sina.com.cn/s/blog_5f66526e0102vf43.html

  如果要解決兩個網站之間的同步登錄(單點登錄)問題,首先來看看一個網站的登錄問題。

  很多人知道一個網站的登錄問題,PHP不就是把通過$_SESSION['user']=array('username'=>'user1');那么,看看php的一句代碼,做了那些操作。以windows下wamp環境配合php的配置文件php.ini看瞧瞧session的相關知識?

  php中默認提供session處理方案,可以在php.ini配置文件中看到有這么兩行,

  session.save_handler=file

  session.save_path = "E:/wamp/tmp",如下圖

  

  這兩句告訴我們,在php中session的處理是文件files的方式,存儲的地方是E:/wamp/tmp,看看我的文件目錄下去

  

  好啦,這就是傳說中的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

 差別不大。

   至此簡單版本的單點登錄基本完成了。

 更多原創博客請看個人獨立博客:傳送門

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM