单点登录简单实现「PHP」

2022-10-11 21:40:31 177 0
魁首哥

先说一下这样做的好处吧,先来三个屌丝域名:

www.abc. com

myspace.abc.com

passport.abc.com

大家都知道,虽然他们都是一个域名但主机名不同,依然不能共享 cookie (没有设置到域名.abc.com),这就导致用户在这些域名之间切换的时候需要重新登录,这是不能忍受的,所以需要同步登录;

先来讨论一下为什么要多个域名吧,我认为应该有一下几个好处;

  1. 功能明确;
  2. 主机名也等于一个参数,在当前restfull,短链接盛行的情况下,还是很有用的;
  3. 便于负载均衡,功能分配;

对于第三点在一些复杂业务逻辑下是非常有用的,当某些功能只能负载到一些特定的主机上时,例如静态文件,大量存储的图片,特别是及时生成的文件等等;

进入正题,能够同步登录,就需要让用户的浏览器记录每个域名的cookie,那么必须要让浏览器请求一次这些主机,方法很简单在页面中加入其他域名的链接如一些浏览器默认不接受第三方的cookie写入,必须添加P3P HTTP header 来尝试(当然并不一定有效);

我简单做了一个demo,加密使用des;编辑/etc/hosts文件添加

127.0.0.1 passport.abc.com

127.0.0.1 www.abc.com

127.0.0.1 myspace.abc.com

passport.abc.com 主要做的事情就是通知其实主机写入cookie;

首先是index.php

session_start();

?>

sync login

hello,游客;请先登录

hello,;进入空间

home

然后是login.php

session_start();

if(!empty($_POST[‘username’])){

require __DIR__.’/Des.php’;

$_SESSION[‘username’] = $_POST[‘username’];

$redirect = ‘

header(‘Location:

}

?>

sync login

这里没有做什么检查,用户登录成功之后,跳转需要什么信息就可以自己添加,这里仅仅传递加密后的用户名(这里的加密是必须的,https就不说了);

在来看看sync.php做了什么

$redirect = empty($_GET[‘redirect’]) ? ‘www.abc.com’ : $_GET[‘redirect’];

if(empty($_GET[‘code’])){

header(‘Loaction:

exit;

}

$apps = array(

‘myspace.abc.com/synclogin/slogin.php’

);

?>

passport

passport.abc.com,请求所有的主机写入cookie,在页面加载完成之后跳转回去;

最后一个slogin.php是每个需要同步登录的域名都需要的用户写入cookie;

session_start();

header(‘Content-Type:text/javascript; charset=utf-8’);

if(!empty($_GET[‘code’])){

require __DIR__.’/Des.php’;

$username = Des::decrypt($_GET[‘code’],’abc’);

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’;}”;//这里只是随便返回

这里分享的都是极简的功能代码,仅仅是描述实现;

最后也分享一下Des.php虽说现在Aes才是最安全的,这里只是简单说明一下;

class Des{

public static function encrypt($data,$key){

$module=mcrypt_module_open(‘des’,”, MCRYPT_MODE_CBC,”);

$key=substr(md5($key),0,mcrypt_enc_get_key_size($module));

srand();

$iv=mcrypt_create_iv(mcrypt_enc_get_iv_size($module), MCRYPT_RAND);

mcrypt_generic_init($module,$key,$iv);

$encrypted=$iv.mcrypt_generic($module,$data);

mcrypt_generic_deinit($module);

mcrypt_module_close($module);

return md5($data).’_’.base64_encode($encrypted);

}

public static function decrypt($data,$key){

$_data = explode(‘_’,$data,2);

if(count($_data)<2){

return false;

}

$data = base64_decode($_data[1]);

$module=mcrypt_module_open(‘des’,”, MCRYPT_MODE_CBC,”);

$key=substr(md5($key),0,mcrypt_enc_get_key_size($module));

$ivSize=mcrypt_enc_get_iv_size($module);

$iv=substr($data,0,$ivSize);

mcrypt_generic_init($module,$key,$iv);

$decrypted=mdecrypt_generic($module,substr($data,$ivSize,strlen($data)));

mcrypt_generic_deinit($module);

mcrypt_module_close($module);

$decrypted = rtrim($decrypted,”\0″);

if($_data[0]!=md5($decrypted)){

return false;

}

return $decrypted;

}

}

PS:这种做法在域名过多之后登陆效率会明显下降, 如果是同一个域名(如abc.com)则不需要以上方法,上面的几个测试域名其实是不需要这样做的 ,只需要在写入cookie时指定domain即可,当然多个主机(如w1.abc.com,w2.abc.com)需要拥有相同的cookie验证策略

收藏
分享
海报
0 条评论
177
上一篇:PHP处理文件上传的函数 下一篇:你应该这个姿势学习PHP(1)

本站已关闭游客评论,请登录或者注册后再评论吧~

忘记密码?

图形验证码