单点登录的实现原理是什么?怎么实现?

简介: 单点登录在现在的系统架构中广泛存在,他将多个子系统的认证体系打通,实现了一个入口多处使用,而在架构单点登录时,也会遇到一些小问题,在不同的应用环境中可以采用不同的单点登录实现方案来满足需求。

作者:一叶知秋 https://dwz.cn/d90vKSJE


单点登录在现在的系统架构中广泛存在,他将多个子系统的认证体系打通,实现了一个入口多处使用,而在架构单点登录时,也会遇到一些小问题,在不同的应用环境中可以采用不同的单点登录实现方案来满足需求。


我将以我所遇到的应用环境以及在其中所经历的各个阶段与大家分享,若有不足,希望各位不吝赐教。


一、共享Session

共享Session可谓是实现单点登录最直接、最简单的方式。将用户认证信息保存于Session中,即以Session内存储的值为用户凭证,这在单个站点内使用是很正常也很容易实现的,而在用户验证、用户信息管理与业务应用分离的场景下即会遇到单点登录的问题,在应用体系简单,子系统很少的情况下,可以考虑采用Session共享的方法来处理这个问题。


image.png


这个架构我使用了基于Redis的Session共享方案。将Session存储于Redis上,然后将整个系统的全局Cookie Domain设置于顶级域名上,这样SessionID就能在各个子系统间共享。分布式Session共享解决方案,这篇推荐大家看下。


这个方案存在着严重的扩展性问题,首先,ASP.NET的Session存储必须为SessionStateItemCollection对象,而存储的结构是经过序列化后经过加密存储的。


并且当用户访问应用时,他首先做的就是将存储容器里的所有内容全部取出,并且反序列化为SessionStateItemCollection对象。


这就决定了他具有以下约束:


1.Session中所涉及的类型必须是子系统中共同拥有的(即程序集、类型都需要一致),这导致Session的使用受到诸多限制;


2.跨顶级域名的情况完全无法处理;


二、基于OpenId的单点登录


这种单点登录将用户的身份标识信息简化为OpenId存放于客户端,当用户登录某个子系统时,将OpenId传送到服务端,服务端根据OpenId构造用户验证信息,多用于C/S与B/S相结合的系统,流程如下:


image.png


由上图可以看到,这套单点登录依赖于OpenId的传递,其验证的基础在于OpenId的存储以及发送。


1.当用户第一次登录时,将用户名密码发送给验证服务;


2.验证服务将用户标识OpenId返回到客户端;


3.客户端进行存储;


4.访问子系统时,将OpenId发送到子系统;


5.子系统将OpenId转发到验证服务;


6.验证服务将用户认证信息返回给子系统;


7.子系统构建用户验证信息后将授权后的内容返回给客户端。


这套单点登录验证机制的主要问题在于他基于C/S架构下将用户的OpenId存储于客户端,在子系统之间发送OpenId,而B/S模式下要做到这一点就显得较为困难。为了处理这个问题我们将引出下一种方式,这种方式将解决B/S模式下的OpenId的存储、传递问题。


三、基于Cookie的OpenId存储方案


我们知道,Cookie的作用在于充当一个信息载体在Server端和Browser端进行信息传递,而Cookie一般是以域名为分割的,例如a.xxx.com与b.xxx.com的Cookie是不能互相访问的,但是子域名是可以访问上级域名的Cookie的。即a.xxx.com和b.xxx.com是可以访问xxx.com下的Cookie的,于是就能将顶级域名的Cookie作为OpenId的载体。


image.png


验证步骤和上第二个方法非常相似:


1、 在提供验证服务的站点里登录;


2、 将OpenId写入顶级域名Cookie里;


3、 访问子系统(Cookie里带有OpenId)


4、 子系统取出OpenId通过并向验证服务发送OpenId


5、 返回用户认证信息


6、 返回授权后的内容


在以上两种方法中我们都可以看到通过OpenId解耦了Session共享方案中的类型等问题,并且构造用户验证信息将更灵活,子系统间的验证是相互独立的,但是在第三种方案里,我们基于所有子系统都是同一个顶级域名的假设,而在实际生产环境里有多个域名是很正常的事情,那么就不得不考虑跨域问题究竟如何解决。


四、B/S多域名环境下的单点登录处理


在多个顶级域名的情况下,我们将无法让各个子系统的OpenId共享。处理B/S环境下的跨域问题,我们首先就应该想到JSONP的方案。


image.png


验证步骤如下:


1、 用户通过登录子系统进行用户登录;


2、 用户登录子系统记录了用户的登录状态、OpenId等信息;


3、 用户使用业务子系统;


4、 若用户未登录业务子系统则将用户跳转至用户登录子系统;


5、 用户子系统通过JSONP接口将用户OpenId传给业务子系统;


6、 业务子系统通过OpenId调用验证服务;


7、 验证服务返回认证信息、业务子系统构造用户登录凭证;(此时用户客户端已经与子业务系统的验证信息已经一一对应)


8、 将用户登录结果返回用户登录子系统,若成功登录则将用户跳转回业务子系统;


9、 将授权后的内容返回客户端;


五、安全问题

经过以上步骤,跨域情况下的单点登录问题已经可以得到解决。而在整个开发过程初期,我们采用用户表中纪录一个OpenId字段来保存用户OpenId,而这个机制下很明显存在一些安全性、扩展性问题。这个扩展性问题主要体现在一个方面:OpenId的安全性和用户体验的矛盾。


整个单点登录的机制决定了OpenId是会出现在客户端的,所以OpenId需要有过期机制,假如用户在一个终端登录的话可以选择在用户每次登录或者每次退出时刷新OpenId,而在多终端登录的情况下就会出现矛盾:当一个终端刷新了OpenId之后其他终端将无法正常授权。


而最终,我采用了单用户多OpenId的解决方案。每次用户通过用户名/密码登录时,产生一个OpenId保存在Redis里,并且设定过期时间,这样多个终端登录就会有多个OpenId与之对应,不再会存在一个OpenId失效所有终端验证都失效的情况。


相关文章
|
JSON 数据格式
uniapp自定义头部导航样式
uniapp自定义头部导航样式
522 0
|
存储 Docker 容器
docker部署etcd集群及使用?
docker部署etcd集群及使用?
663 0
|
7月前
|
人工智能 编解码 芯片
告别低效沟通|让技术提问不再头疼-这套高效AI提问模板来帮你
不会向ai提问,不知道怎么提问的 可以看看
20770 1
告别低效沟通|让技术提问不再头疼-这套高效AI提问模板来帮你
|
6月前
|
API 开发工具 开发者
HarmonyOS NEXT实战:拨打电话
本课程介绍如何在HarmonyOS SDK中使用Telephony Kit实现拨打电话功能。通过CallPhoneDemoPage示例,讲解如何输入电话号码并调用makeCall接口拨号,涉及call模块的使用及设备通话能力检测。
7946 0
|
存储 自然语言处理 搜索推荐
从零开始掌握全文本搜索:快速查找信息的最佳实践
全文本搜索技术(Full-text search)通过关键词或短语快速准确查找文档,其核心在于对文本数据的全面检索和索引。主要步骤包括分词处理、建立倒排索引、关键词匹配和结果排序。常见工具如Lucene、Solr和Elasticsearch提供了强大的搜索功能和高扩展性,适用于大数据和复杂数据分析,广泛应用于搜索引擎、日志分析等领域。
317 0
|
存储 关系型数据库 MySQL
【高频】什么是索引的下推和覆盖
【高频】什么是索引的下推和覆盖
835 2
|
小程序 JavaScript Java
【干货】毕业设计的坑,让工作8年的师狗给你唠唠
本文旨在帮助面临毕业设计的同学解决选题、代码编写及寻求帮助时可能遇到的问题。作者分享了多年经验,建议选择自己擅长的题目,并利用Gitee/Github等平台寻找开源代码作为参考。若需他人协助,务必注意保留付款凭证、分批付款、选择提供售后服务的个人而非公司,并确认支持全额退款,以避免受骗。
263 0
【干货】毕业设计的坑,让工作8年的师狗给你唠唠
字符串和list互转
字符串和list互转
277 0
|
存储 缓存 监控
caffeine本地缓存的使用和详解
在项目中我们经常使用缓存架构,来缓存我们的数据,比如redis、caffeine等。那么redis和caffeine有什么区别?作用又有哪些不同呢?
2233 0
caffeine本地缓存的使用和详解