**定义:**单点登录,即SSO。是在多个应用系统中,用户只需要登陆一次就可以访问所有相互信任的应用系 统。
**为什么要单点登录?**
先说一下这样做的好处吧,先来三个屌丝域名:
www.abc.com
m.abc.com
n.abc.com
大家都知道,虽然他们都是一个域名但主机名不同,依然不能共享cookie(没有设置到域名.openpoor.com),这就导致用户在这些域名之间切换的时候需要重新登录,这是不能忍受的,所以需要同步登录。即一处登录,处处登录。
**案例设计:**在本地服务器测试。同一IP下,不同端口来实现不同站点之间的一次性登录,但是相同IP下会出现session冲突,不过还好,可以通过`ini_set('session.name', 'phpsessid1');`来解决不同端口之间的session冲突问题。具体看【[解决同IP下Session冲突](288242)】。出于最简单的案例展示,只做登录a站点后,b站点也登录。b站点登录,a站点登录,注销这些思路一样,不在做介绍。
**解决思路:**
假设有A站,B站。登录A站访问B站,B站也已经登录。
1.在A站首页(index.php)检测用户是否已经登录。如果已经登录,则显示:你已经登录首页。如果未登录,则返回一个A站登录页的(login.php)链接。
2.在A站登录页中。有个登录表单,可以提交用户名,密码。根据验证规则,检测用户输入的账号和密码是否正确。如果验证成功,则将A站的用户名保存到登录session。说明用户已经在A站登录。同时,页面跳转到A站同步登录页(sync.php),并且将A站用户名通过Des加密,发送给sync.php。
3.在sync.php中,通过js请求的方式,分别请求所有要登录的子站的同步登录页(slogin.php),并且将被加密的用户名传递给他。请求结束后,跳回A站首页。
4.B站的slogin.php。将获取传递过来的被加密的用户名解码传递给用户sesson。
在给B站赋值session的时候,必须遵从P3P标准。不然可能会创建session失败。
5.访问B站的时候,将不会再出现登录。
**资料:P3P**是一种被称为个人隐私安全平台项目(the Platform for Privacy Preferences)的标准,能够保护在线隐私权,使Internet冲浪者可以选择在浏览网页时,是否被第三方收集并利用自己的个人信息。如果一个站点不遵守P3P标准的话,那么有关它的Cookies将被自动拒绝,并且P3P还能够自动识破多种Cookies的嵌入方式。p3p是由全球资讯联盟网所开发的。
代码实现:
A站index.php
~~~
<?php
session_start();
ini_set('session.name', 'phpsessid1');
// s1 为总服务台,登录后,子站c也登录了
if (empty($_SESSION['username'])) {
echo "您还未登录,<a href='/login.php'>请登录!</a>";
}
else{
echo "您好,".$_SESSION['username']."您已经登录了本系统。<a href='/logout.php'>注销</a>";
}
?>
~~~
A站login.php
~~~
<?php
session_start();
?>
<form action="" method="POST" style="text-align: center;">
用户名:<input type="text" name="username"> 密码:<input type="text" name="password"> <input type="submit" name="submit" value="登录">
</form>
<?php
if ($_POST['submit']) {
if ($_POST['username']=="admin" and $_POST['password']=="admin") {
// 登录成功,通知事务
require __DIR__.'/Des.php';
$_SESSION['username'] = $_POST['username'];
$redirect = '/s1.php';
header('Location:/sync.php?redirect='.urlencode($redirect).'&code='.Des::encrypt($_POST['username'],'openpoor'));
exit;
}
}
?>
~~~
A站sync.php
~~~
<?php
// 获取所有的数据
$redirect = empty($_GET['redirect']) ? 'http://localhost:9013' : $_GET['redirect'];
if(empty($_GET['code'])){
header('Loaction:http://'.urldecode($redirect));
exit;
}
$apps=array(
"http://localhost:9012/sync.php",
);
?>
<?php foreach ($apps as $row): ?>
<script type="text/javascript" src="<?php echo $row?>?code='.$_GET['code']";>"></script>
<?php endforeach ?>
<script type="text/javascript">
window.onload=function(){
location.replace('<?php echo $redirect; ?>');
}
</script>
~~~
B站slogin.php
~~~
<?php
session_start();
header('Content-Type:text/javascript; charset=utf-8');
if(!empty($_GET['code'])){
require __DIR__.'/Des.php';
$username = Des::decrypt($_GET['code'],'openpoor');
if(!empty($username)){
header('P3P: CP="CURa ADMa DEVa PSAo PSDo OUR BUS UNI PUR INT DEM STA PRE COM NAV OTC NOI DSP COR"');
$_SESSION['username'] = $username;
}
}
echo "function _(){window.status='ok';}";//这里只是随便返回
~~~
B站首页 index.php
~~~
<?php
session_start();
ini_set('session.name', 'phpsessid2');
if (empty($_SESSION['username'])) {
echo "您还未登录,<a href='/slogin.php'>请登录!</a>";
}
else{
echo "您好,".$_SESSION['username']."您已经登录了本系统。<a href='/logout.php'>注销</a>";
}
~~~