前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >单点登录是怎么回事

单点登录是怎么回事

作者头像
程序猿讲故事
发布2019-09-27 15:32:20
1.5K0
发布2019-09-27 15:32:20
举报
文章被收录于专栏:程序猿讲故事程序猿讲故事

【原创申明:文章为原创,欢迎非盈利性转载,但转载必须注明来源】

单点登录的解决方案有很多,各个解决方案有自己的特点。本文不是为了介绍某一种单点登录方案,只是介绍单点登录的思路,以及必要的技术基础。

一、网站登录是怎么回事

在一个普通的网站开发中,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中即可。

传递token替代userId

前面两种方案,通过链接传输用户ID,都不够安全。一旦黑客拿到了某个用户的userId或加密后的userId密文,他就能欺骗子系统。即使他并没有登录主系统,只需要传递同一个参数值,子系统就会认为该用户已经登陆。

因此可以设计出更安全的单点登录方案,用户访问子系统时,传递一个临时token,而不是真实的userId。

如果用户在主系统以用户 admin 登录,在主系统中生成一个token,保存在session中,并在所有的子系统链接中增加token参数。实际登录子系统过程变成如下:

1) 浏览器访问子系统1: web1.xyz.com?token=t12

2) 子系统拿到token=t12,不认识,它去问主系统:t12是谁?

3) 主系统拿到t12后,在自己维护的会话表中检查了一下,告诉子系统1:这是 admin。

这样,用户就完成了登录子系统1的过程。

⑤ 使用一次性token

前面这个方案,整个会话周期,都是一个token,也不够安全。如果黑客拿到了访问第一个子系统的token,他就能在自己的浏览器中利用这个token访问第二个子系统,顺利完成登录。

这个方案针对方案4做改进,每次构造子系统链接时,生成一个新的token,当子系统验证用户成功后,立刻抛弃这个token,后续用户就不能再使用这个token进行验证。

这个方案还有两个明显的缺点

1) token的生命周期很长,黑客有可能抢在用户登陆子系统之前用token去验证,这样黑客反而抢在了真实用户的前面登录,真实用户进不去了。

2) 需要提前在主系统中为子系统创建链接并添加token参数,不够灵活。

⑥ 使用更成熟的单点登录解决方案

前三种方案都是比较简单的处理方法,不够安全。更安全合理的做法,是基于第三方成熟的解决方案进行定制,或者是参考这些方案,设计更符合环境特点的单点登录方案。

成熟的方案,大致有: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验证的过程对于用户是透明的。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2016-04-26,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 程序猿讲故事 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、网站登录是怎么回事
    • 1. 典型WEB
      • 2. Cookie和Session的关系
        • 3. Cookie和Session的绑定过程
          • ① 用户打开浏览器后第一次访问网站
          • ② 浏览器中后续访问时
          • ③ 用户登录成功时
        • 4. WEB服务器集群部署会有什么问题
          • ① 从前端分发处解决
          • ② Server的Session复制
          • ③ Server共享Session
          • ① 各个系统中自行维护
          • ② 原有的一个主要系统中维护
          • ③ 独立一个用户管理系统
      • 二、单点登录需要解决哪些问题
        • 2. 用户数据同步的机制
          • ① 主系统主动推送
          • ② 子系统定期发起同步请求
          • ③ 用户登录后访问子系统时更新个人信息
        • 3. 用户权限怎么实现
          • ① 各系统自行实现权限定义和判断
          • ② 将权限统一管理
          • ③ 主系统定义部分权限
        • 4. 单点登录的一些备选方案
          • ① 域内Cookie共享
          • ② 传登陆用户的userId明文
          • ③ 传登陆用户的userId密文
          • ④ 传递token替代userId
          • ⑤ 使用一次性token
          • ⑥ 使用更成熟的单点登录解决方案
      • 三、CAS的登录过程
      相关产品与服务
      访问管理
      访问管理(Cloud Access Management,CAM)可以帮助您安全、便捷地管理对腾讯云服务和资源的访问。您可以使用CAM创建子用户、用户组和角色,并通过策略控制其访问范围。CAM支持用户和角色SSO能力,您可以根据具体管理场景针对性设置企业内用户和腾讯云的互通能力。
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档