惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

博客园_首页
T
Threat Research - Cisco Blogs
GbyAI
GbyAI
Y
Y Combinator Blog
美团技术团队
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
博客园 - 【当耐特】
S
SegmentFault 最新的问题
IT之家
IT之家
Recent Announcements
Recent Announcements
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
阮一峰的网络日志
阮一峰的网络日志
T
The Blog of Author Tim Ferriss
Martin Fowler
Martin Fowler
Microsoft Azure Blog
Microsoft Azure Blog
V
Visual Studio Blog
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
U
Unit 42
WordPress大学
WordPress大学
博客园 - Franky
L
LangChain Blog
人人都是产品经理
人人都是产品经理
小众软件
小众软件
博客园 - 叶小钗
罗磊的独立博客
酷 壳 – CoolShell
酷 壳 – CoolShell
大猫的无限游戏
大猫的无限游戏
云风的 BLOG
云风的 BLOG
Vercel News
Vercel News
雷峰网
雷峰网
腾讯CDC
Google DeepMind News
Google DeepMind News
博客园 - 三生石上(FineUI控件)
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
Help Net Security
Help Net Security
C
Check Point Blog
Hacker News - Newest:
Hacker News - Newest: "LLM"
N
News and Events Feed by Topic
V2EX - 技术
V2EX - 技术
Application and Cybersecurity Blog
Application and Cybersecurity Blog
Schneier on Security
Schneier on Security
博客园 - 聂微东
A
Arctic Wolf
H
Heimdal Security Blog
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
Recent Commits to openclaw:main
Recent Commits to openclaw:main
T
The Exploit Database - CXSecurity.com
C
Cyber Attacks, Cyber Crime and Cyber Security
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
Google DeepMind News
Google DeepMind News

青空之蓝

[青空之蓝-2023] - 色彩 | 青空之蓝 [青空之蓝-2022] - 平静 | 青空之蓝 [青空之蓝-2021] - 远望 | 青空之蓝 浅谈垃圾回收 | 青空之蓝 浅谈泛型擦除 | 青空之蓝 使用 Kotlin 编写 Spring 测试 | 青空之蓝 设计模式系列文章 | 青空之蓝 从零实现一个 Java 微框架 - IoC | 青空之蓝 从零实现一个 Java 微框架 - 前言 | 青空之蓝 浅谈 JVM:类加载 | 青空之蓝 浅谈 IO | 青空之蓝 浅谈并发:synchronized & ReentrantLock | 青空之蓝 浅谈并发:CAS & AQS | 青空之蓝 浅谈并发:ThreadLocal | 青空之蓝 浅谈并发:三大特性 | 青空之蓝 浅谈组合注解 & 注解别名 | 青空之蓝 [青空之蓝-2020]-迷茫 | 青空之蓝 Java 系列文章 | 青空之蓝 HTTP 系列文章 | 青空之蓝 浅谈 EatWhatYouKill | 青空之蓝 浅谈可扩展线程池 | 青空之蓝 聊聊写框架 | 青空之蓝 聊聊现状-[2020-09] | 青空之蓝 浅谈并发:锁 | 青空之蓝 浅谈并发:基础 | 青空之蓝 浅谈缓存 | 青空之蓝 无须定义类,Spring 快速注入 Json 参数 | 青空之蓝 浅谈 Proxy 和 Aop | 青空之蓝 从零实现一个 PHP 微框架 - 初始化请求 | 青空之蓝 为 Vue3 添加一个简单的 Store | 青空之蓝 从零实现一个 PHP 微框架 - 服务提供者 | 青空之蓝 WSL2 踩坑记录 | 青空之蓝 浅谈浏览器Event Loop [更新] | 青空之蓝 从零实现一个 PHP 微框架 - Bootstrap 启动加载 | 青空之蓝 从零实现一个 PHP 微框架 - IoC 容器 | 青空之蓝 从零实现一个 PHP 微框架 - PSR & Composer | 青空之蓝 从零实现一个 PHP 微框架 - 前言 | 青空之蓝 MVVM 简单实现 | 青空之蓝 浅谈 DI 和 IoC | 青空之蓝 中间件实现 [PHP] | 青空之蓝 告别 Windows 终端的难看难用,打造好用的 PowerShell | 青空之蓝 VSCode Java输出中文乱码问题解决[更新] | 青空之蓝 浅谈浏览器渲染 | 青空之蓝 Vue-Cli@2 项目迁移日志 | 青空之蓝 Laragon & Scoop 集成踩坑记录 | 青空之蓝 「一行代码」优雅管理 Windows 软件 | 青空之蓝 [青空之蓝-2019]-年度总结 | 青空之蓝 为Vue添加简单的Store | 青空之蓝 为React添加简单的Store | 青空之蓝 为Vuex添加同步Action | 青空之蓝 浅谈B+树 | 青空之蓝 浅谈跳表 | 青空之蓝 浅谈数据库索引 | 青空之蓝 MySQL事务隔离 | 青空之蓝 算法复杂度分析(1) | 青空之蓝 一年来的经验总结 | 青空之蓝 Acrylic - VSCode Extension | 青空之蓝 ace编辑器设置惯性滚动 | 青空之蓝 Java二叉树实现 | 青空之蓝 Java图实现 | 青空之蓝 为apt方式安装的nginx重新编译增加WebDAV | 青空之蓝 XK-Editor - 一个支持富文本和Markdown的编辑器 | 青空之蓝 JS生成列表树 | 青空之蓝 Laravel生成目录树 | 青空之蓝 XK-Note - 集各种神奇功能的云笔记 | 青空之蓝 PHP GD生成验证码 | 青空之蓝 PHP GD图片处理[转换格式-水印-缩略图] | 青空之蓝 Origami - 简洁轻快的WordPress主题 | 青空之蓝 为WordPress启用WorkBox | 青空之蓝 [青空之蓝-2018]-年度总结 | 青空之蓝 VSCode Java手动导入jar和源码包 | 青空之蓝 Windows IP变化自动发送邮件 | 青空之蓝 C链表实现重制版 | 青空之蓝 C 结构体的定义和使用 | 青空之蓝 图的搜索(遍历) - BFS & DFS | 青空之蓝 Java链表实现 | 青空之蓝 C 快速排序 | 青空之蓝 C 插入排序 | 青空之蓝 C 归并排序 | 青空之蓝 C语言链表实现 | 青空之蓝 VSCode配置Java调试环境[Windows] | 青空之蓝 C 选择排序 | 青空之蓝 C 冒泡排序 | 青空之蓝 VSCode配置PHP调试环境[Windows] | 青空之蓝 VSCode配置C/C++ GDB调试环境[Windows] | 青空之蓝 WordPress友情链接模板 | 青空之蓝 Intel Optane 傲腾内存体验 | 青空之蓝 Mysql双机热备实战 | 青空之蓝 博客一年记录 | 青空之蓝 为WordPress启用Service Worker | 青空之蓝 Bing每日一图API | 青空之蓝 iframe延迟加载 | 青空之蓝 写在2018年高考前 | 青空之蓝 The Fox主题汉化分享 | 青空之蓝 [青空之蓝-2017]-崭新 | 青空之蓝 本博客评论规则 | 青空之蓝 世界,您好! | 青空之蓝
浅谈单点登录 | 青空之蓝
Otstar Lin · 2021-06-06 · via 青空之蓝

浅谈单点登录

前言

前不久因为新的项目用到了微服务,有了单点登录的需求,折腾了好几种方案。好久没写文章了,周末还要上课,闲得慌就写了这篇文章。

什么是单点登录

单点登录(Single Sign On),一般简称为 SSO,是整合多系统登录的一种解决方案。

单点登录的定义是在多个应用系统中,用户只需要进行一次登录,即可访问所有被信任的应用系统,而无需再再次登录。

在单点登录的系统一般由一个认证中心,以及多个可信子系统组成。其中认证中心负责处理用户的登录登出操作,当用户登录后,认证中心会返回一个授权令牌(可以是 Token 或其他信息),用户拿到这个授权令牌的时候就可以拿着这个令牌访问其他可信的子系统,子系统拿到用户的授权令牌的时候会进行鉴权,一般是将该令牌交给认证中心进行认证,认证成功后创建局部会话,避免频繁的前往认证中心认证。

举个实际的例子吧:当我们登录淘宝的时候,如果再去访问天猫,天猫就不需要再进行登录操作了,这种就是单点登录。

单系统登录

在了解单点登录前我们先回顾一下单系统登录的方式。由于 HTTP 是无状态的协议,所以服务器无法确认用户的信息。为了解决这个问题,Cookie 和 Session 就因此出现了。举个例子吧,当我们去银行取款的时候,我们需要出示银行卡等证件,这个银行卡就相当于 Cookie,柜台职员就可以因此知道你的身份,而柜台职员拿到你的银行卡的时候就要去查询你银行卡中的余额,此时存放余额信息的数据库就相当于 Session 存储,其中银行卡号就是 Session ID,每个银行卡号对应着一个账户(Session Data)。

在单系统中,当我们进行登录的时候,服务器会把登录的信息存入到 Session 中,并返回一个 Session ID 到 Cookie。当用户访问的时候,浏览器会自动的带上 Cookie,服务器拿到 Session ID 的时候再去查询是否有登录信息。此时由于是单系统,只有一个域名,所以 Cookie 也只有一个,同时 Session 虽然可以使用 Redis 等方式进行分布式部署,但在逻辑上也只能存在一个。

多系统登录

Session 不共享问题

在单系统的登录中,我们一般是使用 Session 来存储登录的用户信息。当系统变成多个了,那么 Session 的存储自然就变成了多个互相隔离的 Session 存储,如下图:

此时如果用户通过左边的系统登录了,那么当用户访问右边的服务的时候,由于 Session 不共享的原因,右边服务的 Session 实际上并没有存在用户的登录信息,系统会判断用户没有登录。

解决方案通常有两种:

  • 同步 Session:当用户登录(修改了 Session)后,此时该系统会将修改的 Session 同步到其他系统上,保证 Session 在逻辑上是单个(一致)的。
  • 集中存储 Session:既然多系统是多导致的不共享问题,那么我们只要把这个多变成单就完事了,第二种方式就是通过将 Session 存储于一个单一的存储系统来解决不共享的问题。通常情况下是使用 Redis 来存储。

在单系统的登录中,一个用户对应了一个 Session,这个对应关系是通过存放于 Cookie 的 Session ID 来实现的。在多系统中,我们通常会为每个系统分配一个不同的域名,由于浏览器默认不会携带其他域名的 Cookie,所以会遇到 Cookie 不共享的问题。

解决方案通常也有两种:

  • 设置父域名 Cookie,使子域名共享使用相同的 Cookie。
  • 利用 Token 代替 Cookie 传输和存储 Session ID,前端发送请求时携带这个 Token。

实现

实现方式有挺多种的,这里就只写几种比较常用的方案吧。

当所有系统的域名都附属于某个父域的时候,如 blog.ixk.menote.ixk.me 就是属于 ixk.me 这个父域名,当 Cookie 设置的域名是父域的时候这时候当访问子域的时候浏览器会自动把设置为父域的所有 Cookie 一起发送到后端,其中包含了 Session ID。

后端利用 Redis 实现共享 Session,拿到通过 Cookie 传入的 Session ID 的时候再到 Redis 查询,取得 Session 数据,其中数据包含了用户登录的信息。

Token + 共享 Session

共享 Cookie + 共享 Session 的方案有一个问题,那就是域名需要有共同的父域名,如果我们的系统有其他的域名如 www.baidu.comblog.ixk.me,这样我们就没法利用到共享 Cookie 的方式了。此时我们要使用 Token,即手动传递 Session ID 的方式,让服务端能取得对应用户的 Session 数据,然后进行登录验证。

后端和共享 Cookie + 共享 Session 的方案一样,使用 Redis 存储 Session 数据。

序列图和共享 Cookie + 共享 Session 一致,只是请求的时候多了个一个 Token 参数,所以这里就不再重复放了。

客户端 Session

还有一种方案是直接抛弃服务端 Session 和 Cookie,直接由客户端存储 Session,每次请求的时候都带上 Session 数据,服务端拿到数据后进行解析和使用,验证用户登录。

但是既然是存放于客户端的数据,那么要怎么防止数据被篡改呢。通常情况下的会使用签名或加密的方式。在登录后,服务端将登录的信息数据进行签名或加密,然后发送到客户端,当客户端请求的时候原封不动的携带这些数据发送到服务端,当服务端拿到后进行签名验证或解密。如果客户端篡改了数据,那么签名验证就会出错,如果是加密的,那么客户端无法看到原文自然也无法篡改。

CAS

CAS(Central Authentication Service)即中心授权服务,是一种实现了 SSO 的授权框架。

认证过程:

  1. 访问 Blog Server。
  2. Blog Server 通过携带的 blog.ixk.me 的 Session ID,取得 Session,发现里面没有登录信息,响应 302 跳转到 cas.ixk.me
  3. 302 自动跳转到 CAS Server
  4. CAS Server 通过携带的 cas.ixk.me 的 Cookie,验证没有登录,302 跳转到 cas.ixk.me 的登录界面。
  5. 用户输入用户名密码登录。
  6. CAS Server 验证用户名密码成功,设置 Cookie,同时 302 到 blog.ixk.me 此时的 302 跳转的 URL 携带了 ticket 的参数。
  7. 302 自动跳转到 Blog Server,携带 ticket。
  8. Blog Server 从参数取得 ticket,携带 ticket 访问 CAS Server,验证是否有效。
  9. CAS Server 验证 ticket 有效,返回用户信息或其他需要的信息。
  10. Blog Server 拿到信息后,存入自己的 Session 中,然后设置 Cookie,同时 302 跳回原本访问的地址,此时客户端可以随意访问 Blog Server 授权的任何端点,Blog Server 在本系统 Session 未过期的时候都不需要再访问 CAS Server。

如果此时用户访问了 Note Server,Note Server 此时并没有用户登录的信息,所以和认证过程 2 一样,跳转到 CAS Server,此时 CAS 的登录还有效,和认证过程 6 一样,302 回 Note Server 同时携带 ticket,Note Server 取得 ticket 后的过程就和认证过程 8-10 一样了。

从上面的流程可以看到,CAS 局部还是使用传统的 Cookie + Session 方式,只是当子系统不存在登录状态的时候将用户重定向到认证中心进行认证,认证中心返回一个 ticket,各子系统再拿着这个 ticket 去认证中心验证。验证成功后就创建局部 Session,此时就和单系统登录差不多了。

OAuth

OAuth 是一种授权框架,允许第三方应用通过用户授权的形式访问服务中的用户信息,最常见的场景是授权登录,它有 4 种访问模式:

  • 授权码模式(Authorization Code)
  • 简化模式(Implicit)
  • 密码模式(Resource owner password credentials)
  • 客户端模式(Client credentials)

其工作流程也和 CAS 类似,不过 OAuth 可以为第三方应用授权,即子系统在访问认证中心前需要事先配置 client_idclient_secret,访问时携带这两个认证数据(授权码模式),此时认证中心才会允许子系统进行访问,这也就使得 OAuth 不在局限于自己的系统,而是可以将认证的功能提供给第三方应用使用,如 Google 和 Github 可以授权给第三方应用认证。

具体的可以看这篇文章:理解 OAuth 2.0 认证流程,文章里已经包含了比较完整的序列图,所以我就不画了,画序列图超级麻烦的 🤣。

结语

写了一个晚上 + 半个下午,写文章挺花时间的。最近都在偷懒和写项目,所以框架的文章一直都没写,等过几天找个时间更新下吧(逃。

浅谈单点登录

https://blog.ixk.me/post/talk-about-single-sign-on
  • 许可协议

    BY-NC-SA

  • 本文作者

    Otstar Lin

  • 发布于

    2021/06/06

转载或引用本文时请遵守许可协议,注明出处、不得用于商业用途!

浅谈泛型擦除使用 Kotlin 编写 Spring 测试