php+ajax實現跨域單點登陸

以前咱們在《SSO單點登陸三種狀況的實現方式詳解》中介紹過跨域單點登陸的原理。這裏向你們介紹利用php和ajax具體實現單點登陸。php

在本次示例中咱們須要兩個站點:html

www.onmpw.com
www.onmpw1.comgit

固然還有一個驗證系統github

www.SSOsite.comajax

爲了實現單點登陸。首先,咱們須要將要設置兩個站點使其共享session。至於如何共享session,能夠參考《PHP集羣session共享》這篇文章。這裏咱們就不作詳細的介紹了。json

假設咱們已經設置了兩者能夠共享session了。下面咱們就來介紹具體實現的流程。跨域

第一部分瀏覽器

下面咱們用文字來描述該過程cookie

·瀏覽器請求onmpw的須要驗證的頁面。session

·經過ajax請求SSOsite系統,查看是否存在SSOsite站點的cookie信息,若是不存在則通知瀏覽器須要進行登陸。

·瀏覽器接收到須要登陸的信息後請求onmpw的登陸頁面(固然有的系統是統一使用SSOsite的登陸系統,那就須要瀏覽器再去請求SSOsite的登陸頁面了)。

·提交登陸信息到onmpw系統。onmpw系統經過curl技術將登陸信息發送給SSOsite系統進行驗證。

curl_setopt($ch, CURLOPT_URL, "www.SSOsite.com/?c=Auth&a=authUser");
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, array('username'=>$username,'password'=>$password));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$data = curl_exec($ch);
$res = json_decode($data);

·SSOsite驗證成功之後,生成token,並將用戶信息連同生成的token一併返回給onmpw系統。

const chars = 'abcdefgABCDEFG012hijklmnHIJKLMN3456opqrstOPQRST789UVWXYZuvwxyz';
static public function str_random(){
     //隨機生成token串
     $chars = self::chars;
     $token = '';
     for($i = 0; $i < 5; $i++){
        $str = substr($chars,0,mt_rand(0, strlen($chars)-1));
        $token .= $str.$chars[mt_rand(0, strlen($str)-1)];
     }
     $token = md5($token);
     return $token;
 }

·onmpw接收到SSOsite返回的驗證成功的信息之後,將用戶信息寫入瀏覽器的cookie中。最後將登陸成功的信息響應給瀏覽器。

setcookie('userid',$res->userid,null,'/');    //設置本站點cookie

·而後瀏覽器再次經過ajax將獲得的token發送給SSOsite。

checkToken:function(args){
         $.ajax({
                   url:Onmpw_SSO.Configure.SSO_Server+'/?c=Auth&a=checkToken',
                   xhrFields: {withCredentials: Onmpw_SSO.Configure.Cross_Domain},
                   dataType:'json',
                   type:'post',
                   data:{token:args.token,userid:args.userid},
                   success:function(data){
                            args.Suc();
                   },
                   error:function(err){
                            console.log(err);
                   }
         })
},

SSOsite獲得token之後將token存入瀏覽器端cookie和session中。

public function checkToken(){
      $this->authUrl();
      session_start();
      if(isset($_POST['token'])){
          setcookie('usertoken',$_POST['token'],null);
          setcookie('userid',$_POST['userid'],null);
          $_SESSION['token'] = $_POST['token'];
          echo json_encode(array('auth'=>'SUC'));
      }
 }

注意在瀏覽器經過ajax向SSOsite發送請求的狀況下須要設置CORS(跨域資源共享)

private function authUrl(){
        $origin = $_SERVER['HTTP_ORIGIN'];
        if (in_array($origin, $this->urlArr)) {
            header("Access-Control-Allow-Origin:" . $origin);
            header("Access-Control-Allow-Credentials: true ");
        }else{
            echo "error!";
            exit;
        }
    }

設置完成之後,返回瀏覽器登陸成功。

第二部分

下面咱們用文字描述該過程

·瀏覽器請求onmpw的須要驗證的頁面。

·經過ajax帶着cookie信息請求SSOsite系統。SSOsite系統在cookie中提取用戶token。而後再次生成一個臨時token存入session中,其鍵名爲用戶token。最後通知瀏覽器該用戶已經登陸成功,而且將臨時token一併返回給瀏覽器。

$tmptoken = \Common::str_random();
$_SESSION[$_SESSION['token']] = $tmptoken;

·瀏覽器接收到臨時token,而後再次經過ajax將臨時token發送給SSOsite進行驗證。SSOsite驗證完成臨時token,將session中的臨時token銷燬。而且獲得本身的sessionId返回給瀏覽器。

public function authToken(){
    $this->authUrl();
    session_start();
    $tmptoken = $_POST['tmptoken'];
    if($tmptoken == $_SESSION[$_SESSION['token']]){
        unset($_SESSION[$_SESSION['token']]);
        echo json_encode(array('auth'=>'SUC','userid'=>$_COOKIE['userid'],'sessionId'=>session_id()));
    }else{
        echo json_encode(array('auth'=>'FAIL'));
    }
 }

·瀏覽器收到SSOsite返回的sessionId之後,將sessionId發送給onmpw。onmpw系統接收到瀏覽器帶來的sessionId之後,用此sessionId來初始化自身的session。將先前存入瀏覽器cookie中的用戶信息存入session中而且銷燬cookie信息(固然在session開啓以後,咱們先檢查session中是否存在用戶信息,若是不存在則將cookie中的用戶信息存入session,並銷燬cookie)。

$sessionId = $_POST['sessionId'];
session_id($sessionId);
session_start();
if(!isset($_SESSION['userid'])){
    $userid = $_COOKIE['userid'];
    setcookie('userid',"",time()-3600,'/');
    $_SESSION['userid'] = $userid;
}

·這樣瀏覽器就能夠知道用戶信息存在,進行相應的操做。在第一部分步驟完成之後,用戶也能夠請求onmpw1。其步驟是和第二部分描述的相同。

至此,經過php和ajax實現跨域單點登陸的流程已經所有完成。其中有一部分核心代碼,能夠點此查看完整代碼。但願本文對你們有所幫助。

相關文章
相關標籤/搜索