php单点登陆简单实现 (iframe方式)
www.a.com
www.b.com
www.c.com
www.sso.com
<iframe src="http://www.a.com/sso.php?sessid=xxx&skey=xxx" width="0" height="0" frameborder="0">
</iframe>
<iframe src="http://www.b.com/sso.php?sessid=xxx&skey=xxx" width="0" height="0" frameborder="0">
</iframe>
<iframe src="http://www.c.com/sso.php?sessid=xxx&skey=xxx" width="0" height="0" frameborder="0">
</iframe>
//sessid是sso.com上产生的session_id
session_id(sessid);
session_start();
<?php
header('Content-Type:text/html;charset=utf-8');
require_once './DBSession.php';
session_start(); if(array_key_exists('userInfo', $_SESSION) && !empty($_SESSION['userInfo'])) {
$userInfo = $_SESSION['userInfo'];
echo '欢迎', $userInfo['name'], '<br />';
echo '<a href="./logout.php">退出</a>';
} else {
header('Location: ./login.html');
}
<!DOCTYPE HTML>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title></title>
<style>
* {padding:0;margin:0;}
.loginForm {width:450px;height:auto;margin:100px auto 0 auto;}
.loginForm table {width:100%;border-collapse:collapse;}
.loginForm table td, .loginForm table th {border:1px solid #dcdcdc;padding:5px;}
</style>
</head>
<body>
<form action="./login.php" method="post" class="loginForm">
<table>
<tr>
<th colspan="2">用户登陆</th>
</tr>
<tr>
<td>用户名:</td>
<td><input type="text" name="uname" value="" /></td>
</tr>
<tr>
<td>密码:</td>
<td><input type="password" name="upwd" value="" /></td>
</tr>
<tr>
<td> </td>
<td><input type="submit" name="submit" value="登陆" /></td>
</tr>
</table>
</form>
</body>
</html>
www.sso.com/login.php
<?php
require_once './DBSession.php';
require_once './DB.php';
session_start(); if(!empty($_POST)) {
$uname = !empty($_POST['uname']) ? trim($_POST['uname']) : '';
$upwd = !empty($_POST['upwd']) ? trim($_POST['upwd']) : ''; $upwd = md5($upwd);
$ret = mysql_query("select `id`,`name` from `user` where `name`='{$uname}' and `pwd`='{$upwd}';", $db);
$data = mysql_fetch_assoc($ret);
if($data) {
$userInfo = array(
'id' => $data['id'],
'name' => $data['name'],
);
$_SESSION['userInfo'] = $userInfo;
//通过用户ID,用户名和时间戳的md5生成skey
$skey = md5($data['id'] . $data['name'] . time());
$sessId = session_id(); $userId = $data['id'];
$ret = mysql_query("update `user` set `sessid`='$sessId', `skey`='$skey' where `id`={$userId};", $db);
if(mysql_affected_rows($db)) { //取skey前三个字符和后三个字符生成key
$key = substr($skey, 0, 3) . substr($skey, -1, 3);
$lifeTime = ini_get('session.gc_maxlifetime');
$sessId = authcode($sessId, 'ENCODE', $key, $lifeTime); $appSSOUrl = array(
'http://www.a.com/sso.php',
'http://www.b.com/sso.php',
'http://www.c.com/sso.php',
); require 'iframe.php';
}
} else {
header('Location: ./login.html');
}
}
<!DOCTYPE HTML>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<?php foreach($appSSOUrl as $item) { ?>
<iframe src="<?php echo $item . '?sessid=' . $sessId . '&skey=' . $skey;?>" width="0" height="0" frameborder="0"></iframe>
<?php } ?>
</body>
<script type="text/javascript">
window.onload = function() {
location.href = 'index.php';
};
</script>
</html>
www.sso.com/logout.php
<?php
require_once './DBSession.php';
require_once './DB.php'; session_start(); if(array_key_exists('userInfo', $_SESSION) && !empty($_SESSION['userInfo'])) {
$uid = $_SESSION['userInfo']['id']; $ret = mysql_query("update `user` set `sessid`='', `skey`='' where id={$uid}", $db);
if(session_destroy()) {
header('Location: ./login.html');
}
}
<?php
header('Content-Type:text/html;charset=utf-8');
require_once './DBSession.php';
session_start(); if(array_key_exists('userInfo', $_SESSION) && !empty($_SESSION['userInfo'])) {
$userInfo = $_SESSION['userInfo'];
echo '欢迎', $userInfo['name'], '<br />';
echo '<a href="http://www.sso.com/logout.php">退出</a>';
} else {
header('Location: http://www.sso.com/login.html');
}
www.a.com/sso.php
<?php
require_once './DBSession.php';
require_once './DB.php'; $sessid = !empty($_GET['sessid']) ? trim($_GET['sessid']) : '';
$skey = !empty($_GET['skey']) ? trim($_GET['skey']) : ''; if(empty($sessid) || empty($skey)) {
exit;
} $key = substr($skey, 0, 3) . substr($skey, -1, 3);
$sessid = authcode($sessid, 'DECODE', $key);
if(!empty($sessid)) {
$ret = mysql_query("select count(*) as num from user where sessid='{$sessid}' and skey='{$skey}'");
$row = mysql_fetch_assoc($ret);
if($row['num']) {
session_id($sessid);
session_start();
}
} else {
header('Location: http://www.sso.com/login.html');
}
b和c站的文件跟a站是一样的,只需复制a站即可,这里就不重复了。
<?php
class DBSession {
protected $db = null;
protected $lifeTime = 0;
protected $sessTable = ''; public function __construct($db, $sessTable) {
$this->db = $db;
$this->sessTable = $sessTable;
$this->lifeTime = ini_get('session.gc_maxlifetime'); ini_set('session.save_handler', 'user');
session_set_save_handler(
array($this, "open"),
array($this, "close"),
array($this, "read"),
array($this, "write"),
array($this, "destroy"),
array($this, "gc")
);
register_shutdown_function('session_write_close');
} public function open($savePath, $sessName) {
return true;
} public function close() {
$this->gc($this->lifeTime);
return true;
} public function read($sessId) {
$time = time();
$ret = mysql_query("SELECT `data` FROM `{$this->sessTable}` WHERE `sid`='{$sessId}' AND `expire` > {$time};", $this->db);
if($ret) {
$row = mysql_fetch_assoc($ret);
return $row['data'];
}
return '';
} public function write($sessId, $sessData) {
$expire = time() + $this->lifeTime;
$sessData = mysql_real_escape_string($sessData); $ret = mysql_query("SELECT COUNT(*) AS cnt FROM `{$this->sessTable}` WHERE `sid`='{$sessId}';", $this->db);
$row = mysql_fetch_assoc($ret);
if($row['cnt']) {
$sql = "UPDATE `{$this->sessTable}` SET `data`='{$sessData}', `expire`={$expire} WHERE `sid`='{$sessId}';";
} else {
$sql = "INSERT INTO `{$this->sessTable}` (`sid`,`expire`,`data`) VALUES('{$sessId}',{$expire},'{$sessData}');";
}
mysql_query($sql, $this->db);
if(mysql_affected_rows($this->db)) {
return true;
}
return false;
} public function destroy($sessId) {
mysql_query("DELETE FROM `{$this->sessTable}` WHERE `sid`='{$sessId}';", $this->db);
if(mysql_affected_rows($this->db)) {
return true;
}
return false;
} public function gc($lifeTime) {
$time = time();
mysql_query("DELETE FROM `{$this->sessTable}` WHERE `expire` < {$time};", $this->db);
return mysql_affected_rows($this->db);
}
} $sessDb = mysql_connect('127.0.0.1', 'root', '') or die('connect error');
mysql_select_db('test', $sessDb) or ('select db error');
mysql_query('set names utf8', $sessDb);
new DBSession($sessDb, 'session');
CREATE TABLE `session` (
`sid` varchar(32) NOT NULL DEFAULT '' COMMENT 'session_id',
`expire` int(11) NOT NULL COMMENT '过期时间',
`data` text COMMENT 'session数据',
PRIMARY KEY (`sid`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='session表';
<?php
$db = mysql_connect('127.0.0.1', 'root', '') or die('connect error');
mysql_select_db('test', $db) or ('select db error');
mysql_query('set names utf8', $db);
user表结构如下:
CREATE TABLE `user` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '用户ID',
`name` varchar(32) NOT NULL DEFAULT '' COMMENT '用户名',
`pwd` varchar(32) NOT NULL DEFAULT '' COMMENT '用户密码(md5)',
`sessid` varchar(32) NOT NULL DEFAULT '' COMMENT 'session_id(未加密)',
`skey` varchar(32) NOT NULL DEFAULT '' COMMENT '安全码',
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 COMMENT='用户表';
function authcode($string, $operation = 'DECODE', $key = '', $expiry = 0){
if($operation == 'DECODE') {
$string = str_replace('[a]','+',$string);
$string = str_replace('[b]','&',$string);
$string = str_replace('[c]','/',$string);
}
$ckey_length = 4;
$key = md5($key ? $key : 'livcmsencryption');
$keya = md5(substr($key, 0, 16));
$keyb = md5(substr($key, 16, 16));
$keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length): substr(md5(microtime()), -$ckey_length)) : '';
$cryptkey = $keya.md5($keya.$keyc);
$key_length = strlen($cryptkey);
$string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string;
$string_length = strlen($string);
$result = '';
$box = range(0, 255);
$rndkey = array();
for($i = 0; $i <= 255; $i++) {
$rndkey[$i] = ord($cryptkey[$i % $key_length]);
}
for($j = $i = 0; $i < 256; $i++) {
$j = ($j + $box[$i] + $rndkey[$i]) % 256;
$tmp = $box[$i];
$box[$i] = $box[$j];
$box[$j] = $tmp;
}
for($a = $j = $i = 0; $i < $string_length; $i++) {
$a = ($a + 1) % 256;
$j = ($j + $box[$a]) % 256;
$tmp = $box[$a];
$box[$a] = $box[$j];
$box[$j] = $tmp;
$result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));
}
if($operation == 'DECODE') {
if((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16)) {
return substr($result, 26);
} else {
return '';
}
} else {
$ustr = $keyc.str_replace('=', '', base64_encode($result));
$ustr = str_replace('+','[a]',$ustr);
$ustr = str_replace('&','[b]',$ustr);
$ustr = str_replace('/','[c]',$ustr);
return $ustr;
}
}


然后我们访问a.com,b.com ,c.com查看

我们点击任一网站退出,其他网站都已退出。
http://www.zhihu.com/question/19779937
php单点登陆简单实现 (iframe方式)的更多相关文章
- 集成基于CAS协议的单点登陆
相信大家对单点登陆(SSO,Single Sign On)这个名词并不感到陌生吧?简单地说,单点登陆允许多个应用使用同一个登陆服务.一旦一个用户登陆了一个支持单点登陆的应用,那么在进入其它使用同一单点 ...
- IM开发基础知识补课:正确理解前置HTTP SSO单点登陆接口的原理
1.前言 一个安全的信息系统,合法身份检查是必须环节.尤其IM这种以“人”为中心的社交体系,身份认证更是必不可少. 一些PC时代小型IM系统中,身份认证可能直接做到长连接中(也就是整个IM系统都是以长 ...
- 在多点环境下使用cas实现单点登陆及登出
CAS 介绍 CAS 是 Yale 大学发起的一个开源项目,旨在为 Web 应用系统提供一种可靠的单点登录方法,CAS 在 2004 年 12 月正式成为 JA-SIG 的一个项目.CAS 具有以下特 ...
- 单点登陆(SSO)
一.背景 在企业发展初期,企业使用的系统很少,通常一个或者两个,每个系统都有自己的登录模块,运营人员每天用自己的账号登录,很方便.但随着企业的发展,用到的系统随之增多,运营人员在操作不同的系统时,需要 ...
- 集成基于OAuth协议的单点登陆
在之前的一篇文章中,我们已经介绍了如何为一个应用添加对CAS协议的支持,进而使得我们的应用可以与所有基于CAS协议的单点登陆服务通讯.但是现在的单点登陆服务实际上并不全是通过实现CAS协议来完成的.例 ...
- Lind.DDD.SSO单点登陆组件的使用(原创)
回到目录 一般sso的说明 在Lind.DDD框架里,有对单点登陆的集成,原理就是各个网站去sso网站统一登陆授权,之后在sso网站将登陆的token进行存储,存储方式随你(cache,redis,m ...
- jQuery简单实现iframe的高度根据页面内容自适应的方法(转)
本文实例讲述了jQuery简单实现iframe的高度根据页面内容自适应的方法.分享给大家供大家参考,具体如下: 方式1: //注意:下面的代码是放在和iframe同一个页面中调用 $("#i ...
- ASP.NET 单点登陆
第一种:同主域但不同子域之间实现单点登陆 Form验证其实是基于身份cookie的验证.客户登陆后,生成一个包含用户身份信息(包含一个ticket)的cookie,这个cookie的名字就是在web. ...
- ASP.NET在不同情况下实现单点登陆(SSO)的方法
第一种:同主域但不同子域之间实现单点登陆 Form验证其实是基于身份cookie的验证.客户登陆后,生成一个包含用户身份信息(包含一个ticket)的cookie,这个cookie的名字就是在web. ...
随机推荐
- 第8章 信号(1)_Linux信号处理机制
1. 信号的基本概念 1.1 基本概念 (1)信号(signal)机制是linux系统中最为古老的进程之间的通信机制,解决进程在正常运行过程中被中断的问题,导致进程的处理流程会发生变化. (2)信号本 ...
- PHP mysqli的prepare准备语句使用说明
mysqli对prepare的支持对于大访问量的网站是很有好处的,它极大地降低了系统开销,而且保证了创建查询的稳定性和安全性.prepare准备语句分为绑定参数和绑定结果,下面将会一一介绍! (1)绑 ...
- php trim() 函数实例讲解
php trim() 函数移除字符串两侧的空白字符或其他预定义字符,本文章向码农介绍php trim() 函数的使用方法和实例,感兴趣的码农可以参考一下. 定义和用法 trim() 函数移除字符串两侧 ...
- php变量详细讲解
变量是用于存储信息的"容器". 定义一个变量的语法: $变量名 = 值; 使用变量的例子: <?php $x=5; $y=6; $z=$x+$y; echo $z; ?> ...
- 洛谷P1414 又是毕业季II
题目背景 “叮铃铃铃”,随着高考最后一科结考铃声的敲响,三年青春时光顿时凝固于此刻.毕业的欣喜怎敌那离别的不舍,憧憬着未来仍毋忘逝去的歌.1000多个日夜的欢笑和泪水,全凝聚在毕业晚会上,相信,这一定 ...
- web service初探
概述:Web service是一个平台独立.低耦合的.自包含的.基于可编程的web的应用程序,可使用开放的XML(标准通用标记语言下的一个子集)标准来描述.发布.发现.协调和配置这些应用程序,用于开发 ...
- Flask上下文管理源码分析
上下文管理本质(类似于threading.local): 1.每一个线程都会在Local类中创建一条数据: { "唯一标识":{stark:[ctx,]}, "唯一标识& ...
- mongodb中查询返回指定字段
mongodb中查询返回指定字段 在写vue项目调用接口获取数据的时候,比如新闻列表页我只需要显示新闻标题和发表时间,点击每条新闻进入详情页的时候才会需要摘要.新闻内容等关于此条新闻的所有字段. ...
- 建造者模式(Builder)
Separate the construction of a complex object form its representation so that the same construction ...
- python中的模块及包及软件目录结构规范
知识内容: 1.模块的定义与分类 2.模块的导入 3.模块与包 4.不同目录下的模块调用 一.模块的定义与分类 1.什么是模块 模块就是实现了某个功能的代码集合,模块是由一大堆代码构成的 类似于函数式 ...