实例教程教你PHP如何实现单点登陆-甜果网|探索和引领技术派电商

https://stackoverflow.com/questions/5062569/how-to-do-single-sign-on-with-php

要理解PHP单点登录的原理,不妨先来看看stackoverflow上的一个高票答案。

首先在需要进行单点登陆的站点构造登录按钮如下:

<a href='http://login.example.com/login.php?source=my.other.site.com/foo/bar'>log in!!</a>

接着,一旦有用户使用这个地址成功登陆,你需要将用户重定向至初始的着陆站点,并且传递相关认证用户的信息。

你需要在你构造的URI上加上规避伪造登陆用户的加密算法签名进行验签。加密算法可以使用HMAC-SHA-256,将自定义的密钥和一系列参数组成签名数据进行HASH。然后在登陆的中心服务器与着陆初始站点进行互相验证。(在整个SSO单点登陆体系的初始站点可以使用不同的密钥)。

<?php
$MySecretKey = 'Nobody Will Ever Guess This!!';

// Generate signature from authentication info + secret key
$sig = hash(
    'sha256',
     $user->id . $user->email,
     $MySecretKey
);

// Make sure we're redirecting somewhere safe
$source = parse_url($_GET['source']);
if(in_array($source->host, $list_of_safe_hosts))
  $target = 'http://'.$source->host.$source->path;

// Send the authenticated user back to the originating site
header('Location: '.$target.'?'.
    'user_id='.$user->id.
    '&user_email='.urlencode($user->email).
    '&sig='.$sig);
?>

接着,在初始站点,如果签名与已登陆的用户匹配,则将用户信息存于session(不是cookie)中。

<?php
$MySecretKey = 'Nobody Will Ever Guess This!!';

// Set not logged in by default
$user_id = 0;
$user_email = '';

if(intval($_GET['user_id']) && !$_SESSION['user_id']) // Someone trying to log in?
{
  // See if they have the right signature
  if (hash_equals(hash('sha256', intval($_GET['user_id']).$_GET['user_email'], $MySecretKey), $sig)) {
    $_SESSION['user_id'] = intval($_GET['user_id']);
    $_SESSION['user_email'] = $_GET['user_email'];
  }
}

?>

如果使用的PHP版本5.6或以上,你可以使用下面的方法:

function hash_equals($a, $b) {
    $key = mcrypt_create_iv(128, MCRYPT_DEV_URANDOM);
    return hash_hmac('sha512', $a, $key) === hash_hmac('sha512', $b, $key);
}

实例教程教你PHP如何实现单点登陆-甜果网|探索和引领技术派电商

通过上面的实例你可以从大概的方向掌握单点登陆。接下来我们聊聊原理:

网站联盟经常会分享一些用户信息,所以一个访问者只需要注册其中一个网站就能在所有相关的网站使用。一个典型的例子就是Google,你可以使用你的google账号登陆GMail,Blogger,google code等站点。实现这个功能就需要SSO(单点登录)。

有许多单点登录应用和协议。大多数都很复杂,这些应用经常来自用户管理,这使得他们很难接入。大多数解决方案也不支持AJAX,因为在SSO服务中通常使用重定向。

实例教程教你PHP如何实现单点登陆-甜果网|探索和引领技术派电商

没有使用 SSO

实例教程教你PHP如何实现单点登陆-甜果网|探索和引领技术派电商

客户端请求主页,页面要求访问者处于登陆状态。服务器新建会话并且发送重定向请求到登陆页。在访客登陆之后显示主页。

使用 SSO 单点登录之后, 将有三个角色:

  • 客户端 - 浏览器访问者
  • 中间者 - 访问站点
  • 服务器 - 保持登录用户信息

 

第一次访问


实例教程教你PHP如何实现单点登陆-甜果网|探索和引领技术派电商

 

访问另一站点


实例教程教你PHP如何实现单点登陆-甜果网|探索和引领技术派电商

 

使用AJAX/JavaScript


 

实例教程教你PHP如何实现单点登陆-甜果网|探索和引领技术派电商

 

总结


通过连接会话,你赋予中间者和客户端一样的权限。这个方法仅仅用在你能够信任所有中间者,登陆信息通过中间者传送,如果中间者想要做坏事的话,能够轻而易举的存储客户信息。