牛骨文教育服务平台(让学习变的简单)
博文笔记

php通过统一发放tickets实现单点登陆SSO功能

创建时间:2015-05-07 投稿人: 浏览次数:270

站点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登陆认证就完成了

声明:该文观点仅代表作者本人,牛骨文系教育信息发布平台,牛骨文仅提供信息存储空间服务。