1. 程式人生 > >php通過統一發放tickets實現單點登陸SSO功能

php通過統一發放tickets實現單點登陸SSO功能

站點a,站點b,站點c,分別跨域,站點b當做統一認證中心,站點a,站點c登入請求轉發到站點b,站點b當做統一登入,註冊中心,也稱第三方身份認證中心;使用者從不同站點登入到第三方認證中心,完成登入驗證後,會生成一個包含使用者登入資訊的加密key,並且生成多個不同子應用的帶加密key的引導頁面,使用者可以自由選擇進入子應用引導頁,完成子頁面認證,從而無需分別登入子應用的登陸入口了,看效果:


通過a站點登入,登入成功後進入第三方登入引導介面:


通過按鈕,附加統一的key,進入a站引導中心


通過按鈕,附加統一的key,進入c站引導中心


已經實現b站點代理登陸,實現a,c站點登陸了,只要b中心,新增多個子站點列表,就可以實現一個登入,註冊中心,一個key實現所有子應用自動登陸,替代了傳統子應用單獨登陸的問題,簡化了使用者操作流程!

公共函式

<?php

function chksecret($secret){
	$key=decode($secret);
	$arr = explode(",",$key);
	if(isset($arr[3]) && $arr[3]=="verifyok"){
		
		$_SESSION['username']=$arr[1];
		$_SESSION['login']=$arr[3];
		
	}else{
	    $url=gethost();
		echo "<script>alert('登陸失敗!');window.location.href='".$url."';</script>";
	}
}
function gethost(){
	return "http://".$_SERVER['HTTP_HOST'];
}

function chklogin(){
	if(isset($_SESSION['login']) && $_SESSION['login']=='verifyok'){
		
	}else{
	    $host=gethost();
		header("location:$host");
	}
}

function decode($string = '', $skey = 'lmj951753') {
    $strArr = str_split(str_replace(array('O0O0O', 'o000o', 'oo00o'), array('=', '+', '/'), $string), 2);
    $strCount = count($strArr);
    foreach (str_split($skey) as $key => $value)
        $key <= $strCount && $strArr[$key][1] === $value && $strArr[$key] = $strArr[$key][0];
    return base64_decode(join('', $strArr));
}

function encode($string = '', $skey = 'lmj951753') {
    $strArr = str_split(base64_encode($string));
    $strCount = count($strArr);
    foreach (str_split($skey) as $key => $value)
        $key < $strCount && $strArr[$key].=$value;
    return str_replace(array('=', '+', '/'), array('O0O0O', 'o000o', 'oo00o'), join('', $strArr));
}

?>


a站登入入口:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
	<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
	<title>a站點</title>
</head>
<body>
	<h1>這是a站</h1>
	<div>
		<form action="http://www.b.com/ssologin.php" method="post">
			<p>使用者名稱:<input type="text" name="username" /></p>
			<p>密  碼:<input type="text" name="password" /></p>
			<p><input type="submit" name='btn' value="登陸"/></p>
		</form>
	</div>
</body>
</html>


a站引導頁:

<?php
require_once('function.php');
session_start();
$secret=isset($_GET['key'])?trim($_GET['key']):'';
if($secret){
	chksecret($secret);
}else{
	chklogin();
}
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
	<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
	<title>登陸引導中心</title>
</head>
<body>
	<p>歡迎回來!這裡是A站點<?php echo $_SESSION['username'] ?></p>
	<p><a href='http://www.a.com/admin.php'>管理中心
		</a>  <a href='http://www.a.com/logout.php'>退出</a>
	</p>
</body>
</html>

sso登陸中心:
<?php

header("Content-type:text/html;charset=utf-8");
$refer=$_SERVER['HTTP_REFERER'];
$username=isset($_POST['username'])?trim($_POST['username']):'';
$password=isset($_POST['password'])?trim($_POST['password']):'';
if(empty($username) || empty($password)){
	goback($refer);
}

$application=array(//根據子站點需要,新增應用列表
	array('name'=>'進入A應用','url'=>'http://www.a.com/'),
	array('name'=>'進入C應用','url'=>'http://www.c.com/')
);

if($username=="admin" && $password=="123456"){
	$str=time().','.$username.",".$password.",verifyok,".$refer;
    $key=encode($str);
    echo "登陸成功!".$username.'<br/>';
    foreach ($application as $k => $v) {
		if($refer==$v['url']){
			echo "<a target='_blank' style='color:red;font-weight:bold' href='".$v['url']."home.php?key=$key'>".$v['name']."</a>  ";
		}else{
			echo "<a target='_blank' href='".$v['url']."home.php?key=$key'>".$v['name']."</a>  ";
		}
    }

}else{
	echo "<script>alert('登陸失敗!');history.go(-1);</script>";
	exit();
}

function goback($refer){
	header("Location:$refer");
	exit();
}

function decode($string = '', $skey = 'lmj951753') {
    $strArr = str_split(str_replace(array('O0O0O', 'o000o', 'oo00o'), array('=', '+', '/'), $string), 2);
    $strCount = count($strArr);
    foreach (str_split($skey) as $key => $value)
        $key <= $strCount && $strArr[$key][1] === $value && $strArr[$key] = $strArr[$key][0];
    return base64_decode(join('', $strArr));
}

function encode($string = '', $skey = 'lmj951753') {
    $strArr = str_split(base64_encode($string));
    $strCount = count($strArr);
    foreach (str_split($skey) as $key => $value)
        $key < $strCount && $strArr[$key].=$value;
    return str_replace(array('=', '+', '/'), array('O0O0O', 'o000o', 'oo00o'), join('', $strArr));
}

?>


c站作為子站點和a站邏輯結構差不多,就不列舉了,一個簡單的基於php實現的sso登陸認證就完成了