以前咱們在《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實現跨域單點登陸的流程已經所有完成。其中有一部分核心代碼,能夠點此查看完整代碼。但願本文對你們有所幫助。