在本次示例中我们需要两个站点:
www.onmpw.com
www.onmpw1.com
www.onmpw1.com
当然还有一个验证系统
www.SSOsite.com
为了实现单点登录。首先,我们需要将要设置两个站点使其共享
session
。
假设我们已经设置了二者可以共享
session
了。下面我们就来介绍具体实现的流程。
第一部分
下面我们用文字来描述该过程
·浏览器请求
onmpw
的需要验证的页面。
·通过
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);
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;
}
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);
}
})
},
$.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'));
}
}
$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'));
}
}
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;
}
}
$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;
$_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'));
}
}
$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;
}
session_id($sessionId);
session_start();
if(!isset($_SESSION['userid'])){
$userid = $_COOKIE['userid'];
setcookie('userid',"",time()-3600,'/');
$_SESSION['userid'] = $userid;
}
·这样浏览器就可以知道用户信息存在,进行相应的操作。在第一部分步骤完成以后,用户也可以请求
onmpw1
。其步骤是和第二部分描述的相同。
原文来自:迹忆的博客