看完这篇你不能再说不懂SSO原理了!

这一篇是原理篇,接下来还会有一篇实战篇,实战的相关代码是非常火的一个开源项目叫:xxl-sso
一、简介
单点登录(Single Sign On),简称为 SSO。
它的解释是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统。
所谓一次登录,处处登录。同样一处退出,处处退出。
二、背景
在我们企业发展初期的时候,企业内部使用的系统都会比较少,一般也就一个或者两个,每个系统有自己的登录功能。运营人员将自己的账号登录还是很方便。
但是随着公司的发展,公司的系统越来越多,比如有OA系统、CRM系统、财务管理系统、设备管理系统等,这个时候总不能每个系统都登录一遍吧,那真的会崩溃的。
合理做法是用户只需要登录一次就可以访问所有相互信任的应用系统。
三、回顾下单系统登录是怎么样的?
我们都知道,http是无状态的协议,这意味着当你登录成功后请求其它接口服务端也并不知道你之前登录过。那怎么办呢?
这个时候我们会想到Cookie+Session组合来解决http无状态问题。
如果说Cookie是检查用户身上的”通行证“来确认用户的身份,那么Session就是通过检查服务器上的”客户明细表“来确认用户的身份的。
那这里完整的登录流程应该是这样的:

1)、 首次登录验证成功之后,后端会将用户信息存在Session对象中。
2)、同时设置 Set-Cookie 字段,并把 SessionId 等信息写入进去,并设置过期时间,这些信息就是 Cookie。浏览器会保存这些 Cookie 信息
3)、之后在请求该系统其它接口的时候,因为是同域名,浏览器会自动在请求头上添加 Cookie 字段,并带上保存的 Cookie 信息。
4)、后端接受到请求后,会在请求头中取出 SessionId的值,然后再去服务器上的Session获取对于的用户信息,如果获取成功说明登录验证成功了,不需要再重复登录。
总结 根据以上流程可知,SessionID 是连接 Cookie 和 Session 的一道桥梁,大部分系统也是根据此原理来验证用户登录状态。
所以,一般我们单系统实现登录会这样做:
登录:将用户信息保存在Session对象中
- 如果在Session对象中能查到,说明已经登录
- 如果在Session对象中查不到,说明没登录(或者已经退出了登录)
注销(退出登录):从Session中删除用户的信息
四、多系统登录会存在的一些问题?
我们说单系统中登录流程实现关键点在于 Cookie 和 Session的配合使用,但在多系统中就会存在很明显的两个问题
- 在多系统情况下服务端
Session不共享。 - 在多系统情况下客户端
Cookie不共享(跨域)。
如果能解决这两大难点,那实现多系统登录就简单多了
1.为什么会存在Session不共享?
我们说Session是存储在服务端的。
比如说现在有3台Tomcat服务器,当我们访问第1台Tomcat时,我们是可以将用户信息存在第1台Tomcat的Session中,但当我们访问第2台Tomcat的时候,这台服务器是
没有对应的Session数据,这就是所谓的Session不共享问题。
2、如何解决session共享问题呢?
说如何解决session共享问题呢,其实就是如何解决服务端数据共享问题
我们常见有3种解决方案:
第一种方案就是session拷贝。
当某一台Tomcat对session中的信息进行了修改都会同步给其他Tomcat,这样session就可以共享。
这种方案有三大缺陷
- 每一台服务器都会存储一份完整的session,增加服务器端压力也会浪费内存。
- 因为涉及到服务之间的同步,所以可能存在延迟。
第二种方案就是不通过session共享数据,而是采用redis。
redis纯天然解决了session不能共享的问题,而且redis除了存储查询效率高以外,还支持数据持久化功能,不用担心数据会丢失。
第二种方案也是现在现在企业级使用最多的一种方案。
第三种采用JWT。
我们在使用session或者使用redis,前端cookie其实只是存了个key,我们还需要拿着这个key到服务端的session,或者redis或者Mysql,总之都需要查一遍,但如果是JWT,
它最大的特点就是这个JWT本身就含有用户信息,服务端只要解析这个JWT成功,就可以获取用户信息。
3、为什么会Cookie跨域问题?
本质:由于浏览器安全策略,cookie只能在同一域名产生和使用
比方说,我们在请求www.a.com的时候,浏览器会自动把www.a.com的Cookie带去服务端。
但我们在请求www.b.com的时候,是不会把www.a.com下的Cookie带到b服务器的。
这就意味着由于域名不同,用户向系统A登录后,系统A返回给浏览器的Cookie,用户再请求系统B的时候不会将系统A的Cookie带过去。
至于如何解决Cookie跨域问题,不在这篇文章的讨论范畴内,下面实现单点登录的方式也不是通过解决Cookie跨域来实现的。
五、单点登录原理
相比于单系统登录,sso需要一个独立的认证中心,只有认证中心能接受用户的用户名密码等安全信息,其他系统不提供登录入口,只接受认证中心的间接授权。
1、SSO应用核心设计

应用系统:OA系统、CRM系统(需要登录的系统)
SSO客户端:登录、退出(独立jar包给应用系统引用)
SSO服务端:登录(登录服务)、登录状态(提供登录状态校验/登录信息查询的服务)、退出(用户注销服务)
数据库:存储用户账户信息(一般使用Mysql)
缓存:存储用户的登录信息(一般使用Redis)
2、SSO登录流程

对于这个流程图,我看网上问的最多的一个问题就是
根据同源策略:只要 协议+域名+端口号 一个不同,那么就不能进行跨域。www.oa.com 和 www.crm.com 域名都不相同了。也就是www.crm.com是
拿不到www.oa.com中cookie中的token的,那crm.com在请求的时候为什么不需要登录呢?
其实这个问题,上面的流程图已经很清楚了。它也并不是通过解决跨域问题来实现单点登录的。
它实现的核心原理在于:
个人用户请求www.oa.com时,因为oa.com的cookie下没有token信息,所以跳转到sso.com/login,因为是第一次登录,所以sso.com的cookie下也没有token信息,所以需要
用户输入账号密码登录,登录成功会在sso.com域名下保存token信息,同时会把token信息返回给oa.com。
这样oa.com和sso.com下的cookie都有token信息。
而第一次访问crm.com的时候,它下面是没有token信息,所以会跳转到sso.com/login进行登录,但因为sso.com域名下cookie已经有token信息,所以不用再输入账号密码信息
直接把token返回到crm.com就可以,这个过程用户是无感知的,所以也就实现了一次登录处处登录了。
3、sso注销流程

对于这个流程,问的比较多的是: oa.com退出登录了。如何做到让crm.com也需要重新登录的?
通过上面的流程图我们可以知道www.oa.com退出登录,只能去除oa.com和sso.com域名下cookie下的token,但是crm.com域名下的cookie还是可以获取token的,
那能获取就代表这可以正常访问www.crm.com的接口了吗?
其实不是的,因为我们还有校验token有效性这一步(令牌校验),我们拿着这个token去redis获取用户信息,其实已经获取不到了,因为上面退出登录的时候已经清除了,
所以令牌校验失败一样要重新登录。
声明: 公众号如需转载该篇文章,发表文章的头部一定要 告知是转至公众号: 后端元宇宙。同时也可以问本人要markdown原稿和原图片。其它情况一律禁止转载!
看完这篇你不能再说不懂SSO原理了!的更多相关文章
- 【最短路径Floyd算法详解推导过程】看完这篇,你还能不懂Floyd算法?还不会?
简介 Floyd-Warshall算法(Floyd-Warshall algorithm),是一种利用动态规划的思想寻找给定的加权图中多源点之间最短路径的算法,与Dijkstra算法类似.该算法名称以 ...
- 看完这篇,还不懂JAVA内存模型(JMM)算我输
欢迎关注专栏[JAVA并发] 更多技术干活尽在个人公众号--JAVA旭阳 前言 开篇一个例子,我看看都有谁会?如果不会的,或者不知道原理的,还是老老实实看完这篇文章吧. @Slf4j(topic = ...
- [转帖]看完这篇文章,我奶奶都懂了https的原理
看完这篇文章,我奶奶都懂了https的原理 http://www.17coding.info/article/22 非对称算法 以及 CA证书 公钥 核心是 大的质数不一分解 还有 就是 椭圆曲线算法 ...
- 看完这篇Redis缓存三大问题,保你面试能造火箭,工作能拧螺丝。
前言 日常的开发中,无不都是使用数据库来进行数据的存储,由于一般的系统任务中通常不会存在高并发的情况,所以这样看起来并没有什么问题. 一旦涉及大数据量的需求,如一些商品抢购的情景,或者主页访问量瞬间较 ...
- APP的缓存文件到底应该存在哪?看完这篇文章你应该就自己清楚了
APP的缓存文件到底应该存在哪?看完这篇文章你应该就自己清楚了 彻底理解android中的内部存储与外部存储 存储在内部还是外部 所有的Android设备均有两个文件存储区域:"intern ...
- 关于 Docker 镜像的操作,看完这篇就够啦 !(下)
紧接着上篇<关于 Docker 镜像的操作,看完这篇就够啦 !(上)>,奉上下篇 !!! 镜像作为 Docker 三大核心概念中最重要的一个关键词,它有很多操作,是您想学习容器技术不得不掌 ...
- [转帖]看完这篇文章你还敢说你懂JVM吗?
看完这篇文章你还敢说你懂JVM吗? 在一些物理内存为8g的服务器上,主要运行一个Java服务,系统内存分配如下:Java服务的JVM堆大小设置为6g,一个监控进程占用大约 600m,Linux自身使用 ...
- 看完这篇还不会 GestureDetector 手势检测,我跪搓衣板!
引言 在 android 开发过程中,我们经常需要对一些手势,如:单击.双击.长按.滑动.缩放等,进行监测.这时也就引出了手势监测的概念,所谓的手势监测,说白了就是对于 GestureDetector ...
- Mysql快速入门(看完这篇能够满足80%的日常开发)
这是一篇mysql的学习笔记,整理结合了网上搜索的教程以及自己看的视频教程,看完这篇能够满足80%的日常开发了. 菜鸟教程:https://www.runoob.com/mysql/mysql-tut ...
- 看完这篇 Linux 权限后,通透了!
我们在使用 Linux 的过程中,或多或少都会遇到一些关于使用者和群组的问题,比如最常见的你想要在某个路径下执行某个指令,会经常出现这个错误提示 . permission denied 反正我大概率见 ...
随机推荐
- 2022春每日一题:Day 16
题目:不同子串个数 这题需要利用后缀数组求出的height的性质,我们发现对于每个后缀,他的height后的所有子串就是算在答案里,因此答案只需要求出n-height[i]-sa[i]+1的和就可以了 ...
- mysql查询结果拼接树结构(树节点的移动)
mysql查询结果拼接树结构(树节点的移动) 思路:单表内查询全部数据,在业务层内递归拼接树结构. 前端用的是element的Tree 树形控件: 树结构实体: @Data @AllArgsConst ...
- Day20.1:关于this、super的解析
this.super详解 当我们在外部程序调用一个类的方法,如果这个类的方法与其父类的方法重载,我们需要用this.super进行区分 this在Java中是一个复杂的关键字,this的使用形式体现了 ...
- JUC-学习笔记
传统的多线程开发方式 implements Runnable public class oldThreadDev implements Runnable { @Override public void ...
- <二>派生类的构造过程
派生类从继承可以继承来所有的成员(变量和方法) 除了构造函数和析构函数 派生类怎么初始化从基类继承来的成员变量的呢?通过调用基类的构造函数来初始化 派生类的构造函数和析构函数,负责初始化和清理派生类部 ...
- postgresql函数:定期删除模式下指定天数前的表数据及分区物理表
一.现有函数-- 1.现有函数调用select ods.deletePartitionIfExists('fact_ship' || '_' || to_char(CURRENT_DATE - INT ...
- openpyxl写数据
import osimport openpyxlos.chdir(r'D:/openpyxl') wb = openpyxl.Workbook() sht = wb.create_sheet('dat ...
- 在nodejs中体验http/2
前言 2015年,HTTP/2 发布,直到2021年公司的项目才开始在实践中应用:自己对http2诸多特点的理解只存在于字面上,于是尝试在nodejs中实践一下,加深自己的理解. 多路复用 同域名下所 ...
- HMS Core 3D流体仿真技术,打造移动端PC级流体动效
移动设备硬件的高速发展,让游戏行业发生翻天覆地的变化,许多酷炫的游戏效果不再局限于电脑端,玩家在移动端就能享受到场景更逼真.画质更清晰.体验更流畅的游戏服务.但由于移动设备算力不足,为了实现真实感的水 ...
- 万万没想到,go的数据库操作,也能像php一样溜了
Hi,各位go的小伙伴. 很多人都是从php转过来的吧,不知道你们有没有发现,go界的orm并没有像php的orm一样好用.这篇文章里,我们认真的讨论下这个问题,并且会在后面提出解决方案. php的方 ...