PHP中SSO Cookie登录分析和实现


Posted in PHP onNovember 06, 2015

什么是SSO?

单点登录SSO(Single Sign-On)是身份管理中的一部分。SSO的一种较为通俗的定义是:SSO是指访问同一服务器不同应用中的受保护资源的同一用户,只需要登录一次,即通过一个应用中的安全验证后,再访问其他应用中的受保护资源时,不再需要重新登录验证

SSO的用途:

目前的企业应用环境中,往往有很多的应用系统,淘宝、天猫、爱淘宝等等产品和如办公自动化(OA)系统,财务管理系统,档案管理系统,信息查询系统等等。这些应用系统服务于企业的信息化建设,为企业带来了很好的效益。但是,用户在使用这些应用系统时,并不方便。用户每次使用系统,都必须输入用户名称和用户密码,进行身份验证;而且应用系统不同,用户账号就不同,用户必须同时牢记多套用户名称和用户密码。特别是对于应用系统数目较多,用户数目也很多的企业,这个问题尤为突出。问题的原因并不是系统开发出现失误,而是缺少整体规划,缺乏统一的用户登录平台,使用SSO技术可以解决以上这些问题

SSO的好处:

方便用户:从用户实际使用角度考虑

用户使用应用系统时,能够一次登录,多次使用。用户不再需要每次输入用户名称和用户密码,也不需要牢记多套用户名称和用户密码。单点登录平台能够改善用户使用应用系统的体验。
方便管理员:从日常维护管理角度考虑

现在很多大的互联网公司都会有很多的应用,比如以下是淘宝网的截图:

PHP中SSO Cookie登录分析和实现

天猫 聚划算 头条等都是不同的应用,有的甚至采用完全不同的域名,但是所有在淘宝注册的用户都是使用的一套用户名和口令,如果在这些系统直接切换做不到登陆状态的同 步,体验是非常差的。再举个栗子,很多公司内部系统也有很多个,比如HR系统,财务系统,考勤系统等等,如果员工在一个系统登陆了,跳转到另外一个系统还 需要登陆,就会让人很不爽...

基于此,SSO(Single Sign On)应运而生。当然,我们来现实这个需求的方法有很多种,使用Cookie是其中比较简单的方式,主要需要解决的问题是:Cookie是不能跨域传递的,如何将一个域的Cookie通知给其它应用(不在同一个域)?

so,如果你对cookie机制不太熟悉,请先google,并大致了解为什么cookie会设计成不能跨域等相关问题。

      系统管理员只需要维护一套统一的用户账号,方便、简单。相比之下,系统管理员以前需要管理很多套的用户账号。每一个应用系统就有一套用户账号,不仅给管理上带来不方便,而且,也容易出现管理漏洞。

简化应用系统开发:从应用扩展角度考虑

      开发新的应用系统时,可以直接使用单点登录平台的用户认证服务,简化开发流程。单点登录平台通过提供统一的认证平台,实现单点登录。因此,应用系统并不需要开发用户认证程序。  
如何实现?

SSO有以下几种方式实现

共享Cookie

当我们的子系统都在一个父级域名下时,我们可以将Cookie种在父域下,这样浏览器同域名下的Cookie则可以共享,这样可以通过Cookie加解密的算法获取用户SessionID,从而实现SSO。

但是,后面我们发现这种方式有几种弊端:
a. 所有同域名的系统都能获取SessionID,易被修改且不安全;
b. 跨域无法使用。

ticket验证,我们目前采取的是这种方式

这种实现的SSO有以下几个步骤:

a. 用户访问某个子系统,发现如果未登录,则引导用户跳转到SSO登录页面;
b. 判断SSO是否已经登录;
c. 如果已经登录,直接跳转到回调地址,并返回认证ticket;
d. 如果未登录,用户正确输入用户名/密码,认证通过跳转到回调地址,并返回认证ticket;
e. 子系统获取ticket,调用SSO获取用户uid等信息,成功后让用户登录。

前面已经说了,如何通过Cookie来实现SSO,主要是如何解决跨域问题。首先来谈谈Set-Cookie中的domain属性。

Cookie domain

为了让Http协议在一定程度上保持上下文,server在响应的头部可以加入Set-Cookie来写入一些数据到客户端,Set-Cookie中的

domain字段用来表示这个cookie所在的域。

栗子:

我们访问www.cookieexm.com,如果server在返回头部中加入了Set-Cookie,如果不指定domain,那么默认这个cookie的域就是www.cookieexm.com,也就是只有访问www.cookieexm.com时客户端才会把这个cookie返给服务端。
如果我们指定domain为.cookieexm.com,那么客户端在访问以下域名:www.cookieexm.com www1.cookieexm.com a.cookieexm.com ***.cookieexm.com 时都能够把cookie返回。

所以,我们得出一条结论:客户端对cookie的domain的匹配是从结尾进行匹配的,有了这个基础,我们就可以实现我们的SSO登陆了。

cookie中需要注意的

设置为http-only

涉及登录凭证(如票据或者用户名)应该加密

cookie不能存放隐私数据

具体方案

假设我们需要在如下子系统 **.a1.a2 **.b1.b2 **.c1.c2间实现单点登录,首先我们需要一个专门用于单点登陆的认证系统(sso.s1.s2)。假设目前系统处于未登录状态,访问www.a1.a2为例:

PHP中SSO Cookie登录分析和实现

分别看一下每个步骤作用:

请求www.a1.a2

www.a1.a2收到请求,检查是否携带登录的cookie,目前没有登陆过,那么重定向到sso认证中心
SSO提供登陆窗口,用户输入用户名 口令。SSO系统验证用户名和口令

这一步是关键,如果登录成功,首先把SSO系统的Cookie放到客户端;同时,将用户的认证信息传递通过重定向传递给业务方,注意,这个传递明显不能通过cookie来传递(不同域嘛),一般是通过加密的querystring。

业务方的验证系统收到sso认证信息,再进行认证
业务方认证通过之后,把认证结果的cookie写入到.a1.a2,至此,SSO认证完成
重定向到业务系统www.a1.a2,由前面的结论可知,此时所有以.a1.a2结尾的业务系统都可以使用这个认证之后的cookie

response

说明:
业务认证系统不一定存在,有些不是太敏感的系统可以直接从SSO Authorization重定向到业务系统,并把SSO的认证信息带过去。

承接上文,此时,如果用户访问www.b1.b2应用,如下图所示:

PHP中SSO Cookie登录分析和实现

与访问www.a1.a2不同的是我们在重定向到SSO Authorization时已经不需要再去输入用户名,因为sso.s1.s2此时已经存有cookie,直接用cookie验证。

以上,就是一个简单的基于Cookie的登陆系统。

其中几个问题需要重点解决

如何高效存储大量临时性的信任数据
如何防止信息传递过程被篡改
如何让SSO系统信任登录系统和免登系统
对于第一个问题,一般可以采用类似与memcached的分布式缓存的方案,既能提供可扩展数据量的机制,也能提供高效访问

对于第二个问题,一般采取数字签名的方法,要么通过数字证书签名,要么通过像md5的方式,这就需要SSO系统返回免登URL的时候对需验证的参数进行 md5加密,并带上token一起返回,最后需免登的系统进行验证信任关系的时候,需把这个token传给SSO系统,SSO系统通过对token的验证 就可以辨别信息是否被改过

对于最后一个问题,可以通过白名单来处理,说简单点只有在白名单上的系统才能请求生产信任关系,同理只有在白名单上的系统才能被免登录。

PHP 相关文章推荐
php图片上传存储源码并且可以预览
Aug 26 PHP
php缓冲 output_buffering的使用详解
Jun 13 PHP
php 获取本地IP代码
Jun 23 PHP
php获取网卡的MAC地址支持WIN/LINUX系统
Apr 30 PHP
php中文验证码实现方法
Jun 18 PHP
十大使用PHP框架的理由
Sep 26 PHP
php+ajax制作无刷新留言板
Oct 27 PHP
[原创]php简单防盗链验证实现方法
Jul 09 PHP
ThinkPHP框架表单验证操作方法
Jul 19 PHP
php精度计算的问题解析
Jun 21 PHP
基于Laravel(5.4版本)的基本增删改查操作方法
Oct 11 PHP
Thinkphp 框架扩展之应用模式实现方法分析
Apr 27 PHP
使用PHP similar text计算两个字符串相似度
Nov 06 #PHP
PHP正则表达式之捕获组与非捕获组
Nov 06 #PHP
php创建无限级树型菜单
Nov 05 #PHP
详解PHP中instanceof关键字及instanceof关键字有什么作用
Nov 05 #PHP
PHP递归创建多级目录
Nov 05 #PHP
PHP中的静态变量及static静态变量使用详解
Nov 05 #PHP
PHP环境中Memcache的安装和使用
Nov 05 #PHP
You might like
[EPIC] Larva vs Flash ZvT @ Crossing Field [2017-10-09]
2020/03/17 星际争霸
DISCUZ 分页代码
2007/01/02 PHP
PHP中static关键字原理的学习研究分析
2011/07/18 PHP
php实现单笔转账到支付宝功能
2018/10/09 PHP
jQuery 页面载入进度条实现代码
2009/02/08 Javascript
javascript(jquery)利用函数修改全局变量的代码
2009/11/02 Javascript
深入理解JavaScript系列(30):设计模式之外观模式详解
2015/03/03 Javascript
jQuery实现类似标签风格的导航菜单效果代码
2015/08/25 Javascript
jquery实现隐藏在左侧的弹性弹出菜单效果
2015/09/18 Javascript
jQuery解析json数据实例分析
2015/11/24 Javascript
购物车前端开发(jQuery和bootstrap3)
2016/08/27 Javascript
Angular2数据绑定详解
2017/04/18 Javascript
Vue2.5通过json文件读取数据的方法
2018/02/27 Javascript
基于Vue中点击组件外关闭组件的实现方法
2018/03/06 Javascript
JavaScript中变量、指针和引用功能与操作示例
2018/08/04 Javascript
JS实现电话号码的字母组合算法示例
2019/02/26 Javascript
微信小程序实现录制、试听、上传音频功能(带波形图)
2020/02/27 Javascript
[00:50]2014DOTA2国际邀请赛 NEWBEE战队回顾
2014/08/01 DOTA
详解Python中的日志模块logging
2015/06/19 Python
python数据类型_字符串常用操作(详解)
2017/05/30 Python
Pandas之Dropna滤除缺失数据的实现方法
2019/06/25 Python
pandas的相关系数与协方差实例
2019/12/27 Python
tensorflow tf.train.batch之数据批量读取方式
2020/01/20 Python
使用CSS3代码绘制可爱的Hello Kitty猫
2016/08/03 HTML / CSS
萨克斯第五大道的折扣店:Saks Fifth Avenue OFF 5TH
2016/08/25 全球购物
Lampenwelt德国:欧洲领先的灯具和照明在线商店
2018/08/05 全球购物
全球性的在线婚纱礼服工厂:27dress.com
2019/03/21 全球购物
IFCHIC台湾:欧美国际设计师品牌
2019/05/18 全球购物
运动会广播稿200米
2014/01/27 职场文书
优秀高中生事迹材料
2014/02/11 职场文书
世界读书日的活动方案
2014/08/20 职场文书
简单的辞职信模板
2015/05/12 职场文书
4种非常实用的python内置数据结构
2021/04/28 Python
JavaScript 反射学习技巧
2021/10/16 Javascript
WINDOWS 64位 下安装配置mysql8.0.25最详细的教程
2022/03/22 MySQL
MySQL数据库查询之多表查询总结
2022/08/05 MySQL