《浅谈架构之路:单点登录 SSO》
前言:SSO 单点登录
“半吊子”的全栈工程师又来了,技术类的文章才发表了两篇,本来想先将主攻的几个系列都开个头(Nodejs、Java、前端、架构、全栈等等),无奈博客起步太晚,写博文的时间又没有很多,只好不按顺序乱发一通,请大家见谅。
本篇文章介绍一下单点登录,不像上一篇博文介绍的前后端分离,SSO 并不能算是一种架构吧,只能说是一个解决方案。由于笔者参与过医院集成平台项目,负责其中单点登录的设计研发工作,将经验总结分享一下,也不一定是最优方案,正确与否那就“仁者见仁智者见智”了。
单点登录(Single Sign On),简称为 SSO,是目前比较流行的企业业务整合的解决方案之一。SSO的定义是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统,即用户只需要记住一组用户名和密码就可以登录所有有权限的系统。
文章导读:开篇先介绍一下笔者从事医疗行业出现单点登录的项目需求,毕竟是需求驱动研发;再将整理的通用版的单点登录知识进行分享;接着介绍一下笔者当前采用集成平台单点登录方案,最后是一些相关扩展。
单点登录背景介绍
随着医院信息化建设的深入,信息化系统越来越多,五花八门多种多样,初步统计目前医院信息化子系统数量已经多达几十个。这些系统的安装维护不仅让信息中心花费大量心血,也让多角色的用户在使用系统时头疼不已。他们在使用系统前首先要寻找系统图标,要记住登录各个系统的用户与密码进行登录验证。找图标、记账户、记密码、这些运用步骤已经让用户觉得医院信息化给他们带来一定的负担。
这时候单点登录就应运而生,他能让用户在运用系统时能准确的寻找到他们需要运用的系统图标,方便他们在安全验证;只需要记住一个密码就可以实现所有有权限运用子系统的登录验证;用户只需要登录一次就可以访问所有相互信任的应用系统,即用户只需要记住一组用户名和密码就可以登录所有有权限的系统。
较大的企业内部,一般都有很多的业务支持系统为其提供相应的管理和IT服务。这些不同的系统往往是在不同的时期建设起来的,运行在不同的平台上;也许是由不同厂商开发,使用了各种不同的技术和标准。为了降低管理的消耗,最大限度的重用已有投资的系统,很多企业都在进行着企业应用集成(EAI)。企业应用集成可以在不同层面上进行:例如在数据存储层面 上的“数据大集中”,在传输层面上的“通用数据交换平台”,在应用层面上的“业务流程整合”,和用户界面上的“通用企业门户”等等。事实上,还用一个层面 上的集成变得越来越重要,那就是“身份认证”的整合,也就是“单点登录”。
通常来说,每个单独的系统都会有自己的安全体系和身份认证系统。整合以前,进入每个系统都需要进行登录,这样的局面不仅给管理上带来了很大的困难,在安全方面也埋下了重大的隐患。使用“单点登录”整合后,只需要登录一次就可以进入多个系统,而不需要重新登录,这不仅仅带来了更好的用户体验,更重要的是降低了安全的风险和管理的消耗。
另外,使用“单点登录”还是SOA时代的需求之一。在面向服务的架构中,服务和服务之间,程序和程序之间的通讯大量存在,服务之间的安全认证是SOA应用的难点之一,应此建立“单点登录”的系统体系能够大大简化SOA的安全问题,提高服务之间的合作效率。
单点登录的机制其实是比较简单的,用一个现实中的例子做比较。颐和园是北京著名的旅游景点,也是我常去的地方。在颐和园内部有许多独立的景点,例如“苏州街”、“佛香阁”和“德和园”,都可以在各个景点门口单独买票。很多游客需要游玩所有德景点,这种买票方式很不方便,需要在每个景点门口排队买票,钱包拿 进拿出的,容易丢失,很不安全。于是绝大多数游客选择在大门口买一张通票(也叫套票),就可以玩遍所有的景点而不需要重新再买票。他们只需要在每个景点门 口出示一下刚才买的套票就能够被允许进入每个独立的景点。
单点登录的机制也一样,如下图所示,当用户第一次访问应用系统1的时候,因为还没有登录,会被引导到认证系统中进行登录(1);根据用户提供的登录信息, 认证系统进行身份效验,如果通过效验,应该返回给用户一个认证的凭据--ticket(2);用户再访问别的应用的时候(3,5)就会将这个ticket 带上,作为自己认证的凭据,应用系统接受到请求之后会把ticket送到认证系统进行效验,检查ticket的合法性(4,6)。如果通过效验,用户就可以在不用再次登录的情况下访问应用系统2和应用系统3了。
集成平台SSO机制详解
当前笔者采用的集成平台单点登录的应用场景和传统企业信息集成里面的单点登录稍有不同,这里引进了三种验证措施:集成平台标识&凭证&令牌号,具体如下:
1、通过服务总线进行各第三方厂家系统的凭证校验,确认消息发送方是可信任系统;
2、通过有时效性的令牌方式进行单次登录操作校验,登录信息在校验通过后由集成平台返回;
3、第三方并不需要摒弃自身的登录功能,因为我们在单点登录的时候,通过集成平台标识来判断进行的是单点登录操作,不影响原有业务;
实现单点登录的前提是员工信息一致性,我们通过员工对照功能保证其信息的一致性。
关于员工对照使用的唯一信息,对于公司的系统,我们采用员工内部序号;而对于其他厂商的外部系统,我们提供“工作牌号”或者“工作牌号+员工姓名”的组合等方式来识别员工,通过程序去适配。
通过员工对照后,系统,科室,角色等其他信息都可以通过接口方式获取,不需要和第三方进行任何对照和关联。在实现员工对照后,其他厂商的系统即可像公司系统那样,按我们的接口文档改造后,顺利接入集成平台。
集成平台的SSO集成在统一工作门户上,作为一个组件展示,医护人员只需要登录门户,就可以方便的进入所有日常需要使用到的医疗系统。
集成平台单点登录的应用场景和传统企业信息集成里面的单点登录稍有不同,平台和第三方系统的对接都是通过WS方式完成,而不是由平台直接操作子系统数据库完成;采用消息中间件的总线方式进行接口管理与操作,增强了数据准确性和流程可控性;同时引进了凭证号,令牌号和集成平台标识这三种验证机制,充分保证了系统的安全性。
单点登录流程:
1)用户登录门户,门户程序会通过服务总线遍历不同厂商的接口,采集该员工在不同子系统拥有的权限,并在SSO组件框中显示子系统列表。
2)用户若需要进入某系统,则点击相应图标,选择登录科室和角色等信息(通过接口获取),此时会在平台这边生成令牌,同时在本地打开相应业务系统,并传递令牌号和集成平台标识。
3)该业务系统识别集成平台标识后,使用令牌来调用平台的令牌验证接口,如果验证成功则利用返回的信息进行登录,错误则给予提示。
PS:上面说的流程是程序实现流程,医护人员使用流程仅仅是登录门户,单击系统直接进入即可,just so so。
关于流程,笔者画了一张简图表示,有点粗糙,凑活着看。

为什么不采用目前流行的Active Directory或者CAS方式实现单点登录?
关于这点,主要出于下面两点考虑:
a)鉴于医院集成平台单点登录的特殊性(同时要对接BS和CS系统),纯web的cookie和session以及CAS等方式不适用。
b)集成平台SSO建设在服务总线基础之上,借助消息中间件,进行所有第三方系统的接口管理,使用令牌和凭证来保证对接及时安全性,同时通过员工主索引的也实现了医院员工统一管理和唯一性确认,在集成平台这样的大背景下,我们为何还要选择需要额外用户权限配置的Active Directory方式呢?
扩展:统一授权机制
嗯,这里为什么突然提到统一授权,这边不是单点登录专题吗?
其实,在实现了单点登录解决方案后,特别是在保证员工一致性、和不同第三方之间系统交互模式建设后,为统一授权也提供了实现方案。
简单介绍一下统一授权的背景:由于全院信息化产品非常丰富,每个独立厂商产品都有独立的系统授权方式。无法给员工统一授权让客户的管理工作人员十分苦恼。如果我们可以将第三方和本公司的产品所有权限都收集到集成平台中进行统一授权,那将大大增加了我们全院信息化的统一性,同时大幅减轻我们客户管理人员的工作压力。
授权内容:授权登录科室,授权使用系统,授权使用系统菜单,授权报表权限,授权一些特定业务权限。
因此,单点登录系统同时集成了统一授权的功能,为不同系统提供代理授权功能,可以直接在单点登录上为不同系统进行角色员工权限分发等工作。
PS:整合了统一授权后,单点登录有了高大上的新名字,“统一登录平台”,囧。。。
PS_2:由于这不是统一授权专场,这边不过多介绍,有时间会再开相应博文。
编后语
单点登录介绍差不多了,每个人对单点登录的理解和实现都各不相同,正所谓:“横看成岭侧成峰,远近高低各不同”。
我们不用去在意这些,抛开实现,其实最重要的还是掌握单点登录的这种思路,并用来解决实际生产生活中的适用的问题。
《浅谈架构之路:单点登录 SSO》的更多相关文章
- 简单物联网:外网访问内网路由器下树莓派Flask服务器
最近做一个小东西,大概过程就是想在教室,宿舍控制实验室的一些设备. 已经在树莓上搭了一个轻量的flask服务器,在实验室的路由器下,任何设备都是可以访问的:但是有一些限制条件,比如我想在宿舍控制我种花 ...
- 利用ssh反向代理以及autossh实现从外网连接内网服务器
前言 最近遇到这样一个问题,我在实验室架设了一台服务器,给师弟或者小伙伴练习Linux用,然后平时在实验室这边直接连接是没有问题的,都是内网嘛.但是回到宿舍问题出来了,使用校园网的童鞋还是能连接上,使 ...
- 外网访问内网Docker容器
外网访问内网Docker容器 本地安装了Docker容器,只能在局域网内访问,怎样从外网也能访问本地Docker容器? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Docker容器 ...
- 外网访问内网SpringBoot
外网访问内网SpringBoot 本地安装了SpringBoot,只能在局域网内访问,怎样从外网也能访问本地SpringBoot? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装Java 1 ...
- 外网访问内网Elasticsearch WEB
外网访问内网Elasticsearch WEB 本地安装了Elasticsearch,只能在局域网内访问其WEB,怎样从外网也能访问本地Elasticsearch? 本文将介绍具体的实现步骤. 1. ...
- 怎样从外网访问内网Rails
外网访问内网Rails 本地安装了Rails,只能在局域网内访问,怎样从外网也能访问本地Rails? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Rails 默认安装的Rails端口 ...
- 怎样从外网访问内网Memcached数据库
外网访问内网Memcached数据库 本地安装了Memcached数据库,只能在局域网内访问,怎样从外网也能访问本地Memcached数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装 ...
- 怎样从外网访问内网CouchDB数据库
外网访问内网CouchDB数据库 本地安装了CouchDB数据库,只能在局域网内访问,怎样从外网也能访问本地CouchDB数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Cou ...
- 怎样从外网访问内网DB2数据库
外网访问内网DB2数据库 本地安装了DB2数据库,只能在局域网内访问,怎样从外网也能访问本地DB2数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动DB2数据库 默认安装的DB2 ...
- 怎样从外网访问内网OpenLDAP数据库
外网访问内网OpenLDAP数据库 本地安装了OpenLDAP数据库,只能在局域网内访问,怎样从外网也能访问本地OpenLDAP数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动 ...
随机推荐
- 微信小程序-未接入app.json错误
微信小程序建立新项目之后会出现app.json文件未接入错误如下图: 一般是因为在下图添加新项目,项目目录这一列,如果不事先建立一个空的文件夹,直接选择则不会出现quickstartup界面 所以在建 ...
- 【转】HashMap实现原理分析
1. HashMap的数据结构 数据结构中有数组和链表来实现对数据的存储,但这两者基本上是两个极端. 数组 数组存储区间是连续的,占用内存严重,故空间复杂的很大.但数组的二分查找时间复杂度小,为O(1 ...
- [Angular Tutorial] 14 -Animations
在这一步中,我们将会通过在我们先前创建的模板代码中添加CSS和JavaScript动画效果来扩展我们的web应用. ·我们现在使用ngAnimate模块来允许动画效果贯穿整个应用. ·我们也依赖于自带 ...
- PHP下的命令行执行
PHP 的命令行模式 以下是 PHP 二进制文件(即 php.exe 程序)提供的命令行模式的选项参数,您随时可以通过 PHP -h 命令来查询这些参数. Usage: php [options] [ ...
- Sublime text追踪函数插件
Sublime Text2/3怎样在Ubuntu中配置CTags插件 | 浏览:1278 | 更新:2014-03-05 10:34 1 2 3 4 5 6 7 分步阅读 本文详解在Ubuntu Li ...
- DEV控件的Gridview1
DEV控件的Gridview小技巧总结 1.设置Gridview控件的某列不可编辑 this.gridData.gridView1.Columns["change_date"].O ...
- IDEA Show Line Number
刚开始用IDEA,经常发现右侧没有显示行号,然后去右键选一下,就显现了 一直没有留意这个现象,刚用vim想删几行数据代码,突然发现没有行号了 明明记得刚刚才右键显示了的 好吧,有行号用着比较顺心了.. ...
- Android性能优化(一)之启动加速35%
一.前言 随着项目版本的迭代,App的性能问题会逐渐暴露出来,而好的用户体验与性能表现紧密相关,从本篇文章开始,我将开启一个Android应用性能优化的专题,从理论到实战,从入门到深挖,手把手将性能优 ...
- Android开发:View的几种布局及实践
引言 View的布局显示方式有下面几种:线性布局(Linear Layout).相对布局(Relative Layout).表格布局(Table Layout).网格视图(Grid View).标签布 ...
- 兼容ie6及以上的表格行滑过时背景色切换的效果
;(function(window){ var tb = document.getElementById('tablelist'); function trfocus(){//为了兼容IE ...