zoukankan      html  css  js  c++  java
  • 单点登录是怎么回事

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

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

    一、网站登录是怎么回事

    在一个普通的网站开发中,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等各种开发语言的子系统集成方案,网络上也有比较丰富的开发文档。当需要提供单点登录方案时,可以有优先考虑它,并进行必要的定制。

  • 相关阅读:
    Android中Context具体解释 ---- 你所不知道的Context
    JDK6、Oracle11g、Weblogic10 For Linux64Bit安装部署说明
    matplotlib 可视化 —— 定制 matplotlib
    matplotlib 可视化 —— 移动坐标轴(中心位置)
    matplotlib 可视化 —— 移动坐标轴(中心位置)
    matplotlib 可视化 —— 定制画布风格 Customizing plots with style sheets(plt.style)
    matplotlib 可视化 —— 定制画布风格 Customizing plots with style sheets(plt.style)
    指数函数的研究
    指数函数的研究
    指数分布的研究
  • 原文地址:https://www.cnblogs.com/codestory/p/5512097.html
Copyright © 2011-2022 走看看