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

www.openpoor.com

myspace.openpoor.com

passport.openpoor.com

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

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

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

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

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

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

127.0.0.1       passport.openpoor.com
127.0.0.1 www.openpoor.com
127.0.0.1 myspace.openpoor.com

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

首先是index.php

<?php session_start(); ?> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"/> <title>sync login</title> </head> <body> <?php if(empty($_SESSION['username'])):?> hello,游客;请先<a href="login.php">登录</a> <?php else: ?> hello,<?php echo $_SESSION['username']; ?>;<a href="http://myspace.openpoor.com/synclogin/index.php">进入空间</a> <?php endif; ?> &nbsp; <a href="http://www.openpoor.com/synclogin/index.php">home</a> </body> </html>

然后是login.php

<?php session_start(); if(!empty($_POST['username'])){ require __DIR__.'/Des.php'; $_SESSION['username'] = $_POST['username']; $redirect = 'http://www.openpoor.com/synclogin/index.php'; header('Location:http://passport.openpoor.com/synclogin/sync.php?redirect='.urlencode($redirect).'&code='.Des::encrypt($_POST['username'],'openpoor'));exit; } ?> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"/> <title>sync login</title> </head> <body> <form action="" method="post"> <input type="text" name="username" placeholder="用户名"/> <input type="text" name="password" placeholder="密码"/> <input type="submit" value="登录"/> </form> </body> </html>

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

在来看看sync.php做了什么

<?php $redirect = empty($_GET['redirect']) ? 'www.openpoor.com' : $_GET['redirect']; if(empty($_GET['code'])){ header('Loaction:http://'.urldecode($redirect)); exit; } $apps = array( 'myspace.openpoor.com/synclogin/slogin.php' ); ?> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"/> <?php foreach($apps as $v): ?> <script type="text/javascript" src="http://<?php echo $v.'?code='.$_GET['code'] ?>"></script> <?php endforeach; ?> <title>passport</title> </head> <body> <script type="text/javascript"> window.onload=function(){ location.replace('<?php echo $redirect; ?>'); } </script> </body> </html>

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

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

<?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';}";//这里只是随便返回

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

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

<?php /** *@see Yii CSecurityManager; */ 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; } }

参考地址:https://my.oschina.net/empty125/blog/215942

php sso 单点登录的实现 代码示例的更多相关文章

  1. oauth2.0实现sso单点登录的方式和相关代码

    SSO介绍 什么是SSO 百科:SSO英文全称Single Sign On,单点登录.SSO是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统.它包括可以将这次主要的登录映射到其他 ...

  2. cas sso单点登录系列4_cas-server登录页面自定义修改过程(jsp页面修改)

    转:http://blog.csdn.net/ae6623/article/details/8861065 SSO单点登录系列4:cas-server登录页面自定义修改过程,全新DIY. 目标:    ...

  3. SSO单点登录系列4:cas-server登录页面自定义修改过程(jsp页面修改)

    落雨 cas 单点登录 SSO单点登录系列4:cas-server登录页面自定义修改过程,全新DIY. 目标:    下面是正文: 打开cas的默认首页,映入眼帘的是满眼的中文and英文混杂体,作为一 ...

  4. 使用 JSONP 实现简单的 SSO 单点登录

    SSO 即 Single Sign On(单点登录).  一.二级域名之间的单点登录 不需要用到JSONP 或者 p3p 协议,直接使用 COOKIE 就行了,因为顶级域名相同就能实现 COOKIE ...

  5. [sso] 单点登录认证流程

    一.流程说明 第一步:访问cas过滤链接ssoLogin,拼凑定向到 CAS_SERVER 获取ticket的URL 第二步:CAS_SERVER校验用户信息,生成Ticket 第三步:重新定向到访问 ...

  6. .NET Core2.0+MVC 用Redis/Memory+cookie实现的sso单点登录

    之前发布过使用session+cookie实现的单点登录,博主个人用的很不舒服,为什么呢,博主自己测试的时候,通过修改host的方法,在本机发布了三个站点,但是,经过测试,发现,三个站点使用的sess ...

  7. Docker 创建 Crucible4.6.1 以及与 Crowd3.3.2 实现 SSO 单点登录

    目录 目录 1.介绍 1.1.什么是 Crucible? 2.Crucible 的官网在哪里? 3.如何下载安装? 4.对 Crucible 进行配置 4.1.破解 Crucible 第一步 4.2. ...

  8. SpringCloud系列——SSO 单点登录

    前言 作为分布式项目,单点登录是必不可少的,文本基于之前的的博客(猛戳:SpringCloud系列——Zuul 动态路由,SpringBoot系列——Redis)记录Zuul配合Redis实现一个简单 ...

  9. [精华][推荐]CAS SSO单点登录服务端客户端学习

    1.通过下载稳定版本的方式下载cas的相关源码包,如下: 直接选择4.2.1的稳定代码即可 2.我们项目中的版本版本使用maven apereo远程库去下载 通过远程maven库下载cas-serve ...

随机推荐

  1. More on wrapper types

    原文地址:http://fsharpforfunandprofit.com/posts/computation-expressions-wrapper-types-part2/ 上一篇中,我们说明了包 ...

  2. luci-bwc

    文件位于:   ../feeds/luci/modules/admin-full/src/luci-bwc.c 功能: Very simple bandwidth collector cache fo ...

  3. Storm源码分析--Nimbus-data

    nimbus-datastorm-core/backtype/storm/nimbus.clj (defn nimbus-data [conf inimbus] (let [forced-schedu ...

  4. java中的字符编码方式

    1. 问题由来 面试的时候被问到了各种编码方式的区别,结果一脸懵逼,这个地方集中学习一下. 2. 几种字符编码的方式 1. ASCII码 我们知道,在计算机内部,所有的信息最终都表示为一个二进制的字符 ...

  5. ios中获取当前屏幕尺寸的方法

    //获取当前屏幕尺寸 CGRect screenFrame = [UIScreen mainScreen].bounds; int screenWidth = screenFrame.size.wid ...

  6. UIAlertAction 弹出对话框9.0后有点变化

    ios 9.0后再用以前的UIAlertAction 已经不行了 被弃用了 改用这种方法了 UIAlertController *alertController = [UIAlertControlle ...

  7. ClassLoader类加载解惑

    1.通过类加载器获取路径: String path = Thread.currentThread().getContextClassLoader().getResource("." ...

  8. jquery的隐藏

    HTML 代码:<form> <input type="text" name="email" /> <input type=&qu ...

  9. Shell脚本常用判断

    -e filename 如果 filename存在,则为真 -d filename 如果 filename为目录,则为真  -f filename 如果 filename为常规文件,则为真 -L fi ...

  10. androidstudio--gsonformat--超爽的数据解析方式

    很久以前写json解析用原始的解析json的方法,后来为了加快开发进度,开始使用gson,fastjson等第三方jar包来进行json解析,为了保持apk足够小,不因为引入jar包导致apk文件过大 ...