在本次示例中我们需要两个站点:
www.onmpw.com
www.onmpw1.com
www.onmpw1.com
当然还有一个验证系统
www.SSOsite.com
为了实现单点登录。首先,我们需要将要设置两个站点使其共享
session
。
假设我们已经设置了二者可以共享
session
了。下面我们就来介绍具体实现的流程。
第一部分
![](http://bbs.zhinengshe.com/data/attachment/forum/201607/01/235042kpyy4ncblzw3t443.png.thumb.jpg)
下面我们用文字来描述该过程
·浏览器请求
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;
}
}
设置完成以后,返回浏览器登录成功。
第二部分
![](http://bbs.zhinengshe.com/data/attachment/forum/201607/01/235123kyeish4ii3e13015.png.thumb.jpg)
下面我们用文字描述该过程
·浏览器请求
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
。其步骤是和第二部分描述的相同。
原文来自:迹忆的博客