sso单点登录PHP实现

来源:互联网 发布:2017年二季度经济数据 编辑:程序博客网 时间:2024/05/16 11:50
单点登录(Single Sign On ),简称为 SSO,是目前比较流行的企业业务整合的解决方案之一。SSO的定义是在多个应 用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统。它包括可以将这次 主要的登录映射到其他应用中用于同一个用户的登录的机制。 
当用户第一次访 问应用系统1的时候,因为还没有登录,会被引导到认证系统中进行登录;根据用户提供的 登录信息,认证系统进行身份效验,如果通过效验,应该返回给用户一个认证的凭据-- ticket;用户再访问别的应用的时候就会将这个ticket带上,作为自己认证的凭据,应用 系统接受到请求之后会把ticket送到认证系统进行效验,检查ticket的合法性。如果通过 效验,用户就可以在不用再次登录的情况下访问应用系统2和应用系统3了。
1.一级域名相同,通过共享cookie来实现
有a.the.com和b.the.com A B两个站点, 只要在A,B任何一个站点登录后,两个网站就都可以使用,不需要在另一个站点登录了。而通过基于cookie的实现方式,前提是两个系统共享一级域名,并且用户要可以唯一标示。上面这两个站点的一级域名是the.com,我们只需要将Cookie的domain属性设置为the.com;具体处理过程如下:当用户在其中某一个站点登录,就设置一个cookie信息,该cookie包含标识用户ID,为了安全,还需要利用对该cookie的值加密。当用户访问其他网站的时候,首先判断是否存在cookie,如果有的话,便解密该cookie,获取用户信息,设置用户为登录状态。
下面是PHP示例代码
function login() //正常的登录
{
.......//验证用户的合法性
setcookie('sign', encrypt($pass), '', '/', 'the.com');
}
funtion sign()
{
$sign = $_COOKIE['sign'];
if(!empty($sign))
{
$sign = decrypt($sign);
..........///登录成功
}
}

这里需要注意的是:加解密一定需要做安全验证。但是这个方法也不够完美,两个站点必须有相同一级域名;另外这种完全基于cookie的方式,安全性不够高。


2.支持多域的单点登陆
需要验证服务器验证服 务器相当于同一入口,任何登陆和注销工作都会通过这里,验证的工作也在这里进行。
a,b,c服务器为业务服务器,d为验证服务器

用户A在a服务器上进行需要验证的操作(比如url_a),a服务器发现用户未登陆, 则跳转到d服务器的登陆页面,d服务器通过A用户验证后,生成用户的cookie,并同时生 成用户的一次性令牌并附加在url_a后面(比如url_a?sign=sign_value)进行跳转,此时a服务器根据传入的sign通过远程调用或者服务器间私有通道调用d服务器的验证服务,d服务器 判断令牌是否有效并删除次令牌,如果通过验证此时a服务器获得用户信息,d服务器记录a 服务器的地址,此时A用户在a服务器上已经登陆了。如果A用户在b或者c服务器上访问需要 验证的操作比如(url_b),则跳转到d服务器的登陆页面,因为已经存在着a用户的 cookie,此时同样生成一次性令牌重复上述过程。

以下是PHP实现的测试类,主要帮助理解如何实现SSO的基本思路

<?php //index.php 应用程序页面 header('Content-Type:text/html; charset=utf-8'); $sso_address = 'http://192.168.122.105/test/sso_test/login.php'; //SSO所在的域名 $callback_address = 'http://'.$_SERVER['HTTP_HOST'].str_replace('index.php','',$_SERVER['SCRIPT_NAME']).'callback.php'; //callback地址用于回调设置cookie if(!$_GET['checked']){//用于验证当前登录状态header('location:'.$sso_address.'?check=1&callback_url='.$_SERVER['HTTP_HOST'].str_replace('index.php','',$_SERVER['SCRIPT_NAME'])); }if(isset($_COOKIE['sign'])){     exit("欢迎您{$_COOKIE['sign']} <a href=\"".$sso_address."?logout=1&callback_url=".$_SERVER['HTTP_HOST'].str_replace('index.php','',$_SERVER['SCRIPT_NAME'])."\">退出</a>"); }else{     echo '您还未登录 <a href="'.$sso_address.'?callback='.$callback_address.'">点此登录</a>'; } ?>

<?php //login.php SSO登录页面 header('Content-Type:text/html; charset=utf-8'); if(isset($_GET['logout'])){ //退出判断    setcookie('sign','',-300);    header('location:http://'.$_GET['callback_url'].'callback.php?logout=1'); exit;} if(isset($_POST['username']) && isset($_POST['password'])){ //登录验证    setcookie('sign',$_POST['username'],0,'');     header("location:".$_POST['callback']."?checked=1&sign={$_POST['username']}"); exit;} if(empty($_COOKIE['sign']) && !$_GET['check']){ ?> <form method="post"> <p>用户名:<input type="text" name="username" /></p> <p>密  码:<input type="password" name="password" /></p> <input type="hidden" name="callback" value="<?php echo $_GET['callback']; ?>" /> <input type="submit" value="登录" /> </form> <?php }elseif(empty($_COOKIE['sign']) && $_GET['check']  ){//没有cookie的情况下检测登录状态    header('location:http://'.$_GET['callback_url'].'callback.php'); exit;}else{    $query = http_build_query($_COOKIE); //有cookie的情况下header('location:http://'.$_GET['callback_url'].'callback.php?'.$query); exit;} ?>

<?php //callback.php 回调页面用来设置跨域COOKIE header('Content-Type:text/html; charset=utf-8'); if(empty($_GET)){setcookie('sign','',-300);     header("location:index.php?checked=1"); }elseif($_GET['logout']){setcookie('sign','',-300); header("location:index.php?checked=1"); }else{     foreach($_GET as $key=>$val){         setcookie($key,$val,0,'');     }    header("location:index.php?checked=1"); }?>

点击登录跳转到SSO登录页面并带上当前应用的callback地址
登录成功后生成COOKIE并将COOKIE传给callback地址
callback地址接收SSO的COOKIE并设置在当前域下再跳回到应用1即完成登录


3.PHP 的 Session 存储方法
session_set_save_handler()函数,这个函数是用来注册用户自定义的 Session 数据存储接口的。
我们只要编写自己的处理函数并进行相应的注册,就可以实现 PHP Session 数据的自定义存储了。比如可以使用 NFS 将 Session 数据存储到统一的网络设备中,也可以将 Session 数据保存到一个数据库中,让所有服务器连接这个共享数据库(比如 MySQL)就可以了。

原创粉丝点击