php sso 单点登录的实现 代码示例
先说一下这样做的好处吧,先来三个屌丝域名:
www.openpoor.com
myspace.openpoor.com
passport.openpoor.com
大家都知道,虽然他们都是一个域名但主机名不同,依然不能共享cookie(没有设置到域名.openpoor.com),这就导致用户在这些域名之间切换的时候需要重新登录,这是不能忍受的,所以需要同步登录;
先来讨论一下为什么要多个域名吧,我认为应该有一下几个好处;
- 功能明确;
- 主机名也等于一个参数,在当前restfull,短链接盛行的情况下,还是很有用的;
- 便于负载均衡,功能分配;
对于第三点在一些复杂业务逻辑下是非常有用的,当某些功能只能负载到一些特定的主机上时,例如静态文件,大量存储的图片,特别是及时生成的文件等等;
进入正题,能够同步登录,就需要让用户的浏览器记录每个域名的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; ?> <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 单点登录的实现 代码示例的更多相关文章
- oauth2.0实现sso单点登录的方式和相关代码
SSO介绍 什么是SSO 百科:SSO英文全称Single Sign On,单点登录.SSO是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统.它包括可以将这次主要的登录映射到其他 ...
- cas sso单点登录系列4_cas-server登录页面自定义修改过程(jsp页面修改)
转:http://blog.csdn.net/ae6623/article/details/8861065 SSO单点登录系列4:cas-server登录页面自定义修改过程,全新DIY. 目标: ...
- SSO单点登录系列4:cas-server登录页面自定义修改过程(jsp页面修改)
落雨 cas 单点登录 SSO单点登录系列4:cas-server登录页面自定义修改过程,全新DIY. 目标: 下面是正文: 打开cas的默认首页,映入眼帘的是满眼的中文and英文混杂体,作为一 ...
- 使用 JSONP 实现简单的 SSO 单点登录
SSO 即 Single Sign On(单点登录). 一.二级域名之间的单点登录 不需要用到JSONP 或者 p3p 协议,直接使用 COOKIE 就行了,因为顶级域名相同就能实现 COOKIE ...
- [sso] 单点登录认证流程
一.流程说明 第一步:访问cas过滤链接ssoLogin,拼凑定向到 CAS_SERVER 获取ticket的URL 第二步:CAS_SERVER校验用户信息,生成Ticket 第三步:重新定向到访问 ...
- .NET Core2.0+MVC 用Redis/Memory+cookie实现的sso单点登录
之前发布过使用session+cookie实现的单点登录,博主个人用的很不舒服,为什么呢,博主自己测试的时候,通过修改host的方法,在本机发布了三个站点,但是,经过测试,发现,三个站点使用的sess ...
- Docker 创建 Crucible4.6.1 以及与 Crowd3.3.2 实现 SSO 单点登录
目录 目录 1.介绍 1.1.什么是 Crucible? 2.Crucible 的官网在哪里? 3.如何下载安装? 4.对 Crucible 进行配置 4.1.破解 Crucible 第一步 4.2. ...
- SpringCloud系列——SSO 单点登录
前言 作为分布式项目,单点登录是必不可少的,文本基于之前的的博客(猛戳:SpringCloud系列——Zuul 动态路由,SpringBoot系列——Redis)记录Zuul配合Redis实现一个简单 ...
- [精华][推荐]CAS SSO单点登录服务端客户端学习
1.通过下载稳定版本的方式下载cas的相关源码包,如下: 直接选择4.2.1的稳定代码即可 2.我们项目中的版本版本使用maven apereo远程库去下载 通过远程maven库下载cas-serve ...
随机推荐
- [POJ] 1562 Oil Deposits (DFS)
Oil Deposits Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 16655 Accepted: 8917 Des ...
- UI弹出键盘和收回键盘
点击textfield,会自动弹出键盘 要让键盘收回来,先设置个代理:[field setTextFieldDelegate:self]; 可设置成自己,也可设置成其他对象,只要在对应的类中,遵循U ...
- Program Files 与Program Files (x86)
在64位系统下,为了更好的兼容32位程序,在安装一些32位程序(注意某些程序他就是32位的),会默认扔到program files(x86)这个文件夹下,而一些64位的程序,或程序本身没有位数区别的, ...
- 把ResultSet对象转变成List对象
private static List<Map<String, Object>> convertRS2List(ResultSet rs) throws SQLExceptio ...
- HDU 4585 Shaolin (set的应用)
set是STL中非常方便的工具,可以实现自动去重和排序,可我一直忽视它的重要性,导致吃了好几次亏. 在思考这道题的时候,我一直往二分上靠拢,可是二分需要直接插入排序,直接插入排序覆盖的时候复杂度最大是 ...
- android基础知识点复习之短信发送
界面布局: activity_main.xml <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/an ...
- 使用OpenCV查找二值图中最大连通区域
http://blog.csdn.net/shaoxiaohu1/article/details/40272875 使用OpenCV查找二值图中最大连通区域 标签: OpenCVfindCoutour ...
- nefu 753 n!末尾有多少个0
Problem : 753 Time Limit : 1000ms Memory Limit : 65536K description 计算N!末尾有多少个0 input 输入数据有多组,每组1行,每 ...
- Sharepoint 弹出消息提示框 .
在event receiver中如何弹出一个类似winform中messagebox.show 的框? 那我要对用户显示一些错误信息或者提示信息怎么搞? 1. 如果是在ItemAdding或者其他进行 ...
- CentOS + EPEL YUM源地址
[bizosv] name=bizsov-centos-$releasever - centos baseurl=http://yikat:yikat@download.bizsov.com/ gpg ...