单点登录是怎么回事
Posted 程序猿讲故事
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了单点登录是怎么回事相关的知识,希望对你有一定的参考价值。
【原创申明:文章为原创,欢迎非盈利性转载,但转载必须注明来源】
单点登录的解决方案有很多,各个解决方案有自己的特点。本文不是为了介绍某一种单点登录方案,只是介绍单点登录的思路,以及必要的技术基础。
一、网站登录是怎么回事
在一个普通的网站开发中,Web Server怎么知道当前用户是谁?
1. 典型WEB
在典型的WEB应用中,应用大致包含三类数据:用户数据、权限数据、业务数据。用户打开浏览器后,首先跳转到登录界面,登录成功后就可以继续访问。下图是一个简单的描述。
问题来了,在登录成功后的后续访问中,服务器是怎么知道当前请求的用户到底是谁呢?我们都知道,HTTP是无连接的协议,每次浏览器的请求,对服务器来说都是一个新的请求,它怎么知道是上次登录的那个浏览器上发来的?
这就要提到两个概念:Cookie和Session。如果完全不懂这几个概念,自行找点编程书看看吧,还不太适合看这篇文章。
2. Cookie和Session的关系
在浏览器中,会维护一个Cookie,JavaWeb中这个Cookie名叫jsessionid。在Web Server中,会维护一个SessionMap,将一个jsessionid同一个Session对象进行绑定。这样,当浏览器访问时的jsessionid这个Cookie送到服务器后,服务器就能得到所对应的Session对象。
3. Cookie和Session的绑定过程
Cookie和Session的绑定过程如下
① 用户打开浏览器后第一次访问网站
用户第一次访问,服务器会创建一个新的Session对象和Cookie,实现二者的绑定,并将Cookie写入到用户浏览器中。
② 浏览器中后续访问时
用户后续访问时,浏览器会读出Cookie随同Request提交到服务器上,服务器根据Cookie,查找到当前浏览器对应的Session信息。
③ 用户登录成功时
用户登录成功后,服务器会在当前用户的Session中写入用户信息。
下次用户访问时,服务器根据Cookie得到用户的Session,就可以从中读出当前用户的信息。
4. WEB服务器集群部署会有什么问题
将WEB服务器部署为集群,如果不做任何设置,用户会话可能会出现丢失。
当用户在Server1中登录后,在Server1中创建了Session。如果下次用户被分发到Server2,这时候会无法得到Session信息,导致系统异常。
① 从前端分发处解决
让同一个浏览器发送来的请求,永远分发到同一台Server。
② Server的Session复制
③ Server共享Session
多个Server,可以配置使用一个共享的Session信息,比如使用Redis保存会话。
二、单点登录需要解决哪些问题
整个应用环境,已经有很多套系统在运行,各自有自己的用户管理、登录管理。突然老板说要把所有的系统用户整合在一起,实现单点登录。怎么办?
1. 用户数据如何维护
原有的每个系统,都有自己的用户管理,整合单点登录后,怎么处理?大致会有以下一些处理方案:
① 各个系统中自行维护
这种方案最简单,用户管理部分不用做任何变化。但是需要做一些约定:相同的用户应该使用同一个登录名;用户在一个系统中进行了维护,必须在其他系统中同时维护。
② 原有的一个主要系统中维护
原有的系统中,如果有一个侧重于用户信息管理的系统,可以将这个系统作为用户维护的主系统,其他系统不再保留用户管理功能,而改为从这个主系统中同步。
③ 独立一个用户管理系统
构建一套独立的用户管理系统,独立于原有的各个系统。如,使用LDAP、Windows Exchange。原有的用户系统都从这套系统中进行用户同步。
2. 用户数据同步的机制
前面采用了第二或第三种方案后,需要考虑用户数据如何同步的问题。可以考虑的有几种方案。为描述方便,将负责用户管理的系统称为主系统,其他系统成为子系统。
① 主系统主动推送
各系统实现同步信息变更接口。当用户信息变更后,主系统主动向所有子系统推送用户变更信息。这样,能保证用户信息得到实时的更新。
这种方案的缺点:1、更新时某个子系统正在存在故障,更新失败,以后可能找不到更新的时机了;2、某个子系统部署位置特殊,不能被主系统访问。
② 子系统定期发起同步请求
主系统实现同步接口,由子系统定期主动发起同步请求。主系统将某个时间段之后的所有变更,按照特定格式封装后返回给子系统,由子系统负责解析并更新到本地用户表。
③ 用户登录后访问子系统时更新个人信息
用户登录后,跳转到子系统时,从主系统中查询当前用户的信息,并同子系统进行比较,如有变更则更新本地用户信息。
这种方案的缺点:1、如果用户不访问子系统,永远没有更新的机会;2、用户被删除或禁用,没有机会更新子系统。
三种方案各有特点,可根据情况选择,或者同时用多种方案配合实现。
3. 用户权限怎么实现
用户信息统一管理后,一个随之而来的问题,就是权限信息如何管理?简单分析,大致有三种解决方案:
① 各系统自行实现权限定义和判断
这个方案最简单,对原有系统不做任何修改。
这个方案有一个缺点:各个子系统的超级管理员如何设置。原来可能是将admin或root作为超管,可能各个子系统对超管账号设置不同,就会碰到定义困难。
② 将权限统一管理
在用户管理主系统中,同时定义角色、权限等信息,在主系统中实现用户权限设置,并在用户跳转到子系统时,能够准确的读取到用户在本系统中的授权信息。
这个方案对更适用于新开发的系统,权限从头开发。针对老系统改造,可能修改工作量比较大。
③ 主系统定义部分权限
将前面两种方案整合,可以做一个新方案:由主系统定义子系统的部分权限,更多权限由各个子系统自行定义。
比如,主系统只需定义各个子系统的超级管理员。
4. 如何实现单点登录
前面分析了用户和权限的改造,它们是为统一用户做基础准备工作。现在该讨论核心问题:如何实现单点登录?
列出一些能想到的解决方案。有些方案看似问题很大,但真有人这么做,因为:做起来简单。
① 域内Cookie共享
这是利用Cookie的特点,它是按照域名存储的。如果多个应用使用的是同一个域名,则这些应用都能读取到同一个Cookie。
如图,用户在主系统中登录后,创建一个cookie,域名设置为xyz.com。这时候,*.xyz.com的所有服务器,都能读取到这个域名。如果不指定域名,缺省使用的是主系统的域名www.xyz.com,其他子系统就不能读取同一个Cookie了。
子系统读取到userId这个cookie后,知道这是登录用户的id,从数据库中读取对应用户的信息并保存到Session中即可。
② 传登陆用户的userId明文
用户在主系统中登录后,在主系统中提供子系统链接,并将用户说的唯一标识通过参数传递给子系统。
子系统读取到这个userId后,知道这是登录用户的id,从数据库中读取对应用户的信息并保存到Session中即可。
③ 传登陆用户的userId密文
如果觉得传输用户的userId明文不够安全,可以考虑将参数值加密进行传输。
子系统接收到userId参数的密文后,首先解密,知道这是登录用户的id,从数据库中读取对应用户的信息并保存到Session中即可。
④ 使用更成熟的单点登录解决方案
前三种方案都是比较简单的处理方法,不够安全。更安全合理的做法,是基于第三方成熟的解决方案进行定制,或者是参考这些方案,设计更符合环境特点的单点登录方案。
成熟的方案,大致有:CAS、OAuth1.0/2.0、OpenID,以及QQ等第三方提供的单点登录接入方案。
其中,CAS是一个非常成熟的解决方案,并且有Java、php等各种开发语言的子系统集成方案,网络上也有比较丰富的开发文档。当需要提供单点登录方案时,可以有优先考虑它,并进行必要的定制。
三、CAS的登录过程
网络上已经有丰富的CAS文档,我就不做拷贝粘贴的工作了。简单从网络上拷贝一段介绍CAS的登录过程,主要是为了同前述几个简单方案的区别。
【复制自:http://blog.csdn.net/nengyu/article/details/7086110】
CAS Client 与受保护的客户端应用部署在一起,以Filter方式保护 Web 应用的受保护资源,过滤从客户端过来的每一个 Web请求,同时, CAS Client会分析HTTP 请求中是否包请求 Service Ticket( 上图中的 Ticket) ,如果没有,则说明该用户是没有经过认证的,于是,CAS Client会重定向用户请求到CAS Server( Step 2 )。 Step 3是用户认证过程,如果用户提供了正确的Credentials, CAS Server 会产生一个随机的 Service Ticket ,然后,缓存该 Ticket ,并且重定向用户到CAS Client(附带刚才产生的Service Ticket), Service Ticket 是不可以伪造的,最后, Step 5 和 Step6是 CAS Client 和 CAS Server之间完成了一个对用户的身份核实,用Ticket查到 Username ,因为 Ticket是 CAS Server 产生的,因此,所以 CAS Server 的判断是毋庸置疑的。
该协议完成了一个很简单的任务,所有与CAS的交互均采用SSL协议,确保ST和TGC的安全性。协议工作过程会有2此重定向过程,但是CAS Client与CAS Server之间进行ticket验证的过程对于用户是透明的。
以上是关于单点登录是怎么回事的主要内容,如果未能解决你的问题,请参考以下文章