diff --git a/README.md b/README.md index 5ecdc116eb33e78660f751374f2079f11460d226..b95dda7d1370a57c375fce6a7d0692bb5ba43f90 100644 --- a/README.md +++ b/README.md @@ -36,43 +36,61 @@ Github用户如果访问速度缓慢的话,可以转移到[码云](https://git - [容器](#容器) - [并发](#并发) - [JVM](#jvm) - - [其他(IO/Java8/编码规范)](#其他) + - [其他](#其他) - [网络](#网络) - [操作系统](#操作系统) - - [Linux相关](#linux相关) + - [Linux](#linux) - [数据结构与算法](#数据结构与算法) - [数据结构](#数据结构) - [算法](#算法) - [数据库](#数据库) - [MySQL](#mysql) - [Redis](#redis) - - [数据库扩展](#数据库扩展) - [系统设计](#系统设计) - - [常用框架(Spring,SpringBoot,MyBatis)](#常用框架) - - [数据通信/中间件(消息队列、RPC ... )](#数据通信中间件) - - [权限认证](#权限认证) - - [分布式 & 微服务](#分布式--微服务) - - [API 网关](#api-网关) - - [配置中心](#配置中心) - - [唯一 id 生成](#唯一-id-生成) - - [服务治理:服务注册与发现、服务路由控制](#服务治理服务注册与发现服务路由控制) + - [常用框架](#常用框架) + - [Spring](#spring) + - [SpringBoot](#springboot) + - [MyBatis](#mybatis) + - [认证授权(JWT、SSO)](#认证授权) + - [分布式](#分布式) + - [SSO(单点登录)](#sso单点登录) + - [Elasticsearch(分布式搜索引擎)](#elasticsearch分布式搜索引擎) + - [RPC](#rpc) + - [消息队列](#消息队列) + - [API 网关](#api-网关) + - [唯一 id 生成](#唯一-id-生成) + - [ZooKeeper](#zookeeper) + - [数据库扩展](#数据库扩展) - [大型网站架构](#大型网站架构) - - [性能测试](#性能测试) - - [高并发](#高并发) - - [高可用](#高可用) - - [设计模式(工厂模式、单例模式 ... )](#设计模式) + - [性能测试](#性能测试) + - [高并发](#高并发) + - [高可用](#高可用) + - [微服务](#微服务) + - [Spring Cloud](#spring-cloud) + - [配置中心](#配置中心) - [面试指南](#面试指南) - [备战面试](#备战面试) + - [真实面试经历分析](#真实面试经历分析) - [面经](#面经) - [Java学习常见问题汇总](#java学习常见问题汇总) - [工具](#工具) - [Git](#git) - - [Docker](#Docker) + - [Docker](#docker) + - [其他](#其他-1) - [资源](#资源) - [书单](#书单) - - [Github榜单](#Github榜单) + - [实战项目推荐](#实战项目推荐) + - [Github](#github) - [待办](#待办) - [说明](#说明) + - [JavaGuide介绍](#javaguide介绍) + - [作者的其他开源项目推荐](#作者的其他开源项目推荐) + - [关于转载](#关于转载) + - [如何对该开源文档进行贡献](#如何对该开源文档进行贡献) + - [为什么要做这个开源文档?](#为什么要做这个开源文档) + - [投稿](#投稿) + - [联系我](#联系我) + - [公众号](#公众号) ## Java @@ -128,16 +146,19 @@ Github用户如果访问速度缓慢的话,可以转移到[码云](https://git 1. **I/O** :[BIO,NIO,AIO 总结 ](docs/java/BIO-NIO-AIO.md) 2. **Java 8** :[Java 8 新特性总结](docs/java/What's%20New%20in%20JDK8/Java8Tutorial.md)、[Java 8 学习资源推荐](docs/java/What's%20New%20in%20JDK8/Java8教程推荐.md)、[Java8 forEach 指南](docs/java/What's%20New%20in%20JDK8/Java8foreach指南.md) 3. **[Java 编程规范以及优雅 Java 代码实践总结](docs/java/Java编程规范.md)** +4. 设计模式 :[设计模式系列文章](docs/system-design/设计模式.md) ## 网络 -* [计算机网络常见面试题](docs/network/计算机网络.md) -* [计算机网络基础知识总结](docs/network/干货:计算机网络知识总结.md) -* [HTTPS中的TLS](docs/network/HTTPS中的TLS.md) +1. [计算机网络常见面试题](docs/network/计算机网络.md) +2. [计算机网络基础知识总结](docs/network/干货:计算机网络知识总结.md) +3. [HTTPS中的TLS](docs/network/HTTPS中的TLS.md) ## 操作系统 -### Linux相关 +操作系统相关概念总结 + +### Linux * [后端程序员必备的 Linux 基础知识](docs/operating-system/后端程序员必备的Linux基础知识.md) * [Shell 编程入门](docs/operating-system/Shell.md) @@ -177,10 +198,6 @@ Github用户如果访问速度缓慢的话,可以转移到[码云](https://git * [如何做可靠的分布式锁,Redlock真的可行么](docs/database/Redis/如何做可靠的分布式锁,Redlock真的可行么.md) * [几种常见的 Redis 集群以及使用场景](docs/database/Redis/redis集群以及应用场景.md) -### 数据库扩展 - -待办...... - ## 系统设计 ### 常用框架 @@ -201,17 +218,42 @@ Github用户如果访问速度缓慢的话,可以转移到[码云](https://git - [MyBatis常见面试题总结](docs/system-design/framework/mybatis/mybatis-interview.md) -### 数据通信/中间件 +### 认证授权 + +**[认证授权基础:搞清Authentication,Authorization以及Cookie、Session、Token、OAuth 2、SSO](docs/system-design/authority-certification/basis-of-authority-certification.md)** + +#### JWT + +- **[JWT 优缺点分析以及常见问题解决方案](docs/system-design/authority-certification/JWT-advantages-and-disadvantages.md)** +- **[适合初学者入门 Spring Security With JWT 的 Demo](https://github.com/Snailclimb/spring-security-jwt-guide)** + +#### SSO(单点登录) + +SSO(Single Sign On)即单点登录说的是用户登陆多个子系统的其中一个就有权访问与其相关的其他系统。举个例子我们在登陆了京东金融之后,我们同时也成功登陆京东的京东超市、京东家电等子系统。 + +相关阅读:[SSO 单点登录看这篇就够了!](docs/system-design/authority-certification/sso.md) + +### 分布式 -- [数据通信(RESTful、RPC、消息队列)相关知识点总结](docs/system-design/data-communication/summary.md) +[分布式相关概念入门](docs/system-design/website-architecture/分布式.md) + +#### Elasticsearch(分布式搜索引擎) + +提高搜索效率。常见于电商购物网站的商品搜索于分类。 + +代办...... #### RPC +让调用远程服务调用像调用本地方法那样简单。 + - [Dubbo 总结:关于 Dubbo 的重要知识点](docs/system-design/data-communication/dubbo.md) - [服务之间的调用为啥不直接用 HTTP 而用 RPC?](docs/system-design/data-communication/why-use-rpc.md) #### 消息队列 +消息队列在分布式系统中主要是为了接耦和削峰。 + - [消息队列总结](docs/system-design/data-communication/message-queue.md) **RabbitMQ:** @@ -229,37 +271,17 @@ Github用户如果访问速度缓慢的话,可以转移到[码云](https://git - [Kafka系统设计开篇-面试看这篇就够了](docs/system-design/data-communication/Kafka系统设计开篇-面试看这篇就够了.md) - [【加餐】Kafka入门看这一篇就够了](docs/system-design/data-communication/Kafka入门看这一篇就够了.md) -### 权限认证 - -- **[权限认证基础:区分Authentication,Authorization以及Cookie、Session、Token](docs/system-design/authority-certification/basis-of-authority-certification.md)** -- **[JWT 优缺点分析以及常见问题解决方案](docs/system-design/authority-certification/JWT-advantages-and-disadvantages.md)** -- **[适合初学者入门 Spring Security With JWT 的 Demo](https://github.com/Snailclimb/spring-security-jwt-guide)** - -### 分布式 & 微服务 - -- [分布式应该学什么](docs/system-design/website-architecture/分布式.md) - -#### Spring Cloud - -- [ 大白话入门 Spring Cloud](docs/system-design/micro-service/spring-cloud.md) - #### API 网关 网关主要用于请求转发、安全认证、协议转换、容灾。 - [浅析如何设计一个亿级网关(API Gateway)](docs/system-design/micro-service/API网关.md) -#### 配置中心 - -待办...... - #### 唯一 id 生成 - [分布式id生成方案总结](docs/system-design/micro-service/分布式id生成方案总结.md) -#### 服务治理:服务注册与发现、服务路由控制 - -**ZooKeeper:** +#### ZooKeeper > 前两篇文章可能有内容重合部分,推荐都看一遍。 @@ -267,6 +289,12 @@ Github用户如果访问速度缓慢的话,可以转移到[码云](https://git - [【进阶】Zookeeper 原理简单入门!](docs/system-design/framework/ZooKeeper-plus.md) - [【拓展】ZooKeeper 数据模型和常见命令](docs/system-design/framework/ZooKeeper数据模型和常见命令.md) +#### 数据库扩展 + +读写分离、分库分表。 + +代办..... + ### 大型网站架构 - [8 张图读懂大型网站技术架构](docs/system-design/website-architecture/8%20张图读懂大型网站技术架构.md) @@ -284,9 +312,15 @@ Github用户如果访问速度缓慢的话,可以转移到[码云](https://git - [如何设计一个高可用系统?要考虑哪些地方?](docs/system-design/website-architecture/如何设计一个高可用系统?要考虑哪些地方?.md) -### 设计模式 +### 微服务 -- [设计模式系列文章](docs/system-design/设计模式.md) +#### Spring Cloud + +- [ 大白话入门 Spring Cloud](docs/system-design/micro-service/spring-cloud.md) + +#### 配置中心 + +待办...... ## 面试指南 @@ -365,6 +399,8 @@ Github用户如果访问速度缓慢的话,可以转移到[码云](https://git ### JavaGuide介绍 +开源 JavaGuide 初始想法源于自己的个人那一段比较迷茫的学习经历。主要目的是为了通过这个开源平台来帮助一些在学习 Java 或者面试过程中遇到问题的小伙伴。 + * **对于 Java 初学者来说:** 本文档倾向于给你提供一个比较详细的学习路径,让你对于Java整体的知识体系有一个初步认识。另外,本文的一些文章 也是你学习和复习 Java 知识不错的实践; * **对于非 Java 初学者来说:** 本文档更适合回顾知识,准备面试,搞清面试应该把重心放在那些问题上。要搞清楚这个道理:提前知道那些面试常见,不是为了背下来应付面试,而是为了让你可以更有针对的学习重点。 @@ -389,14 +425,6 @@ Markdown 格式参考:[Github Markdown格式](https://guides.github.com/featur 2. 很多知识点我可能没有涉及到,所以你可以对其他知识点进行补充。 3. 现有的知识点难免存在不完善或者错误,所以你可以对已有知识点进行修改/补充。 -### 为什么要做这个开源文档? - -初始想法源于自己的个人那一段比较迷茫的学习经历。主要目的是为了通过这个开源平台来帮助一些在学习 Java 或者面试过程中遇到问题的小伙伴。 - -### 投稿 - -由于我个人能力有限,很多知识点我可能没有涉及到,所以你可以对其他知识点进行补充。大家也可以对自己的文章进行自荐,对于不错的文章不仅可以成功在本仓库展示出来更可以获得作者送出的 50 元左右的任意书籍进行奖励(当然你也可以直接折现50元)。 - ### 联系我 ![个人微信](https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/2019-7/wechat3.jpeg) @@ -465,3 +493,5 @@ Markdown 格式参考:[Github Markdown格式](https://guides.github.com/featur **Java工程师必备学习资源:** 一些Java工程师常用学习资源公众号后台回复关键字 **“1”** 即可免费无套路获取。 ![我的公众号](https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/2019-6/167598cd2e17b8ec.png) + + diff --git a/docs/system-design/authority-certification/basis-of-authority-certification.md b/docs/system-design/authority-certification/basis-of-authority-certification.md index 896353f6f80cf7573a6d81ceec136699727db676..3080ebcf415e4a00d9637c6527b81c725c8aa9ce 100644 --- a/docs/system-design/authority-certification/basis-of-authority-certification.md +++ b/docs/system-design/authority-certification/basis-of-authority-certification.md @@ -4,8 +4,13 @@ 说简单点就是: -- **认证 (Authentication):** 你是谁。 -- **授权 (Authorization):** 你有权限干什么。 +**认证 (Authentication):** 你是谁。 + + + +**授权 (Authorization):** 你有权限干什么。 + + 稍微正式点(啰嗦点)的说法就是: @@ -16,6 +21,8 @@ ## 2. 什么是Cookie ? Cookie的作用是什么?如何在服务端使用 Cookie ? +![](https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/2019-11/cookie-sessionId.png) + ### 2.1 什么是Cookie ? Cookie的作用是什么? Cookie 和 Session都是用来跟踪浏览器用户身份的会话方式,但是两者的应用场景不太一样。 @@ -28,7 +35,7 @@ Cookie 和 Session都是用来跟踪浏览器用户身份的会话方式,但 2. 使用Cookie 保存 session 或者 token ,向后端发送请求的时候带上 Cookie,这样后端就能取到session或者token了。这样就能记录用户当前的状态了,因为 HTTP 协议是无状态的。 3. Cookie 还可以用来记录和分析用户行为。举个简单的例子你在网上购物的时候,因为HTTP协议是没有状态的,如果服务器想要获取你在某个页面的停留状态或者看了哪些商品,一种常用的实现方式就是将这些信息存放在Cookie -### 2.2 如何能在 服务端使用 Cookie 呢? +### 2.2 如何在服务端使用 Cookie 呢? 这部分内容参考:https://attacomsian.com/blog/cookies-spring-boot,更多如何在Spring Boot中使用Cookie 的内容可以查看这篇文章。 @@ -91,13 +98,56 @@ public String readAllCookies(HttpServletRequest request) { 4. 当用户保持登录状态时,Cookie 将与每个后续请求一起被发送出去。 5. 服务器可以将存储在 Cookie 上的 Session ID 与存储在内存中或者数据库中的 Session 信息进行比较,以验证用户的身份,返回给用户客户端响应信息的时候会附带用户当前的状态。 +使用 Session 的时候需要注意下面几个点: + +1. 依赖Session的关键业务一定要确保客户端开启了Cookie。 +2. 注意Session的过期时间 + +花了个图简单总结了一下Session认证涉及的一些东西。 + + + 另外,Spring Session提供了一种跨多个应用程序或实例管理用户会话信息的机制。如果想详细了解可以查看下面几篇很不错的文章: - [Getting Started with Spring Session](https://codeboje.de/spring-session-tutorial/) - [Guide to Spring Session](https://www.baeldung.com/spring-session) - [Sticky Sessions with Spring Session & Redis](https://medium.com/@gvnix/sticky-sessions-with-spring-session-redis-bdc6f7438cc3) -## 4. 什么是 Token?什么是 JWT?如何基于Token进行身份验证? +## 4.如果没有Cookie的话Session还能用吗? + +这是一道经典的面试题! + +一般是通过 Cookie 来保存 SessionID ,假如你使用了 Cookie 保存 SessionID的方案的话, 如果客户端禁用了Cookie,那么Seesion就无法正常工作。 + +但是,并不是没有 Cookie 之后就不能用 Session 了,比如你可以将SessionID放在请求的 url 里面`https://javaguide.cn/?session_id=xxx` 。这种方案的话可行,但是安全性和用户体验感降低。当然,为了你也可以对 SessionID 进行一次加密之后再传入后端。 + +## 5.为什么Cookie 无法防止CSRF攻击,而token可以? + +**CSRF(Cross Site Request Forgery)**一般被翻译为 **跨站请求伪造** 。那么什么是 **跨站请求伪造** 呢?说简单用你的身份去发送一些对你不友好的请求。举个简单的例子: + +小壮登录了某网上银行,他来到了网上银行的帖子区,看到一个帖子下面有一个链接写着“科学理财,年盈利率过万”,小壮好奇的点开了这个链接,结果发现自己的账户少了10000元。这是这么回事呢?原来黑客在链接中藏了一个请求,这个请求直接利用小壮的身份给银行发送了一个转账请求,也就是通过你的 Cookie 向银行发出请求。 + +``` +科学理财,年盈利率过万 +``` + +上面也提到过,进行Session 认证的时候,我们一般使用 Cookie 来存储 SessionId,当我们登陆后后端生成一个SessionId放在Cookie中返回给客户端,服务端通过Redis或者其他存储工具记录保存着这个Sessionid,客户端登录以后每次请求都会带上这个SessionId,服务端通过这个SessionId来标示你这个人。如果别人通过 cookie拿到了 SessionId 后就可以代替你的身份访问系统了。 + + Session 认证中 Cookie 中的 SessionId是由浏览器发送到服务端的,借助这个特性,攻击者就可以通过让用户误点攻击链接,达到攻击效果。 + +但是,我们使用 token 的话就不会存在这个问题,在我们登录成功获得 token 之后,一般会选择存放在 local storage 中。然后我们在前端通过某些方式会给每个发到后端的请求加上这个 token,这样就不会出现 CSRF 漏洞的问题。因为,即使有个你点击了非法链接发送了请求到服务端,这个非法请求是不会携带 token 的,所以这个请求将是非法的。 + +需要注意的是不论是 Cookie 还是 token 都无法避免跨站脚本攻击(Cross Site Scripting)XSS。 + +> 跨站脚本攻击(Cross Site Scripting)缩写为 CSS 但这会与层叠样式表(Cascading Style Sheets,CSS)的缩写混淆。因此,有人将跨站脚本攻击缩写为XSS。 + +XSS中攻击者会用各种方式将恶意代码注入到其他用户的页面中。就可以通过脚本盗用信息比如cookie。 + +推荐阅读: + +1. [如何防止CSRF攻击?—美团技术团队](https://tech.meituan.com/2018/10/11/fe-security-csrf.html) + +## 6. 什么是 Token?什么是 JWT?如何基于Token进行身份验证? 我们在上一个问题中探讨了使用 Session 来鉴别用户的身份,并且给出了几个 Spring Session 的案例分享。 我们知道 Session 信息需要保存一份在服务器端。这种方式会带来一些麻烦,比如需要我们保证保存 Session 信息服务器的可用性、不适合移动端(依赖Cookie)等等。 @@ -132,7 +182,7 @@ JWT 由 3 部分构成: - [JSON Web Token 入门教程](https://www.ruanyifeng.com/blog/2018/07/json_web_token-tutorial.html) - [彻底理解Cookie,Session,Token](https://mp.weixin.qq.com/s?__biz=Mzg2OTA0Njk0OA==&mid=2247485603&idx=1&sn=c8d324f44d6102e7b44554733da10bb7&chksm=cea24768f9d5ce7efe7291ddabce02b68db34073c7e7d9a7dc9a7f01c5a80cebe33ac75248df&token=844918801&lang=zh_CN#rd) -## 5 什么是OAuth 2.0? +## 7 什么是OAuth 2.0? OAuth 是一个行业的标准授权协议,主要用来授权第三方应用获取有限的权限。而 OAuth 2.0是对 OAuth 1.0 的完全重新设计,OAuth 2.0更快,更容易实现,OAuth 1.0 已经被废弃。详情请见:[rfc6749](https://tools.ietf.org/html/rfc6749)。 @@ -140,6 +190,12 @@ OAuth 是一个行业的标准授权协议,主要用来授权第三方应用 OAuth 2.0 比较常用的场景就是第三方登录,当你的网站接入了第三方登录的时候一般就是使用的 OAuth 2.0 协议。 +另外,现在OAuth 2.0也常见于支付场景(微信支付、支付宝支付)和开发平台(微信开放平台、阿里开放平台等等)。 + +微信支付账户相关参数: + + + **推荐阅读:** - [OAuth 2.0 的一个简单解释](http://www.ruanyifeng.com/blog/2019/04/oauth_design.html) @@ -147,6 +203,14 @@ OAuth 2.0 比较常用的场景就是第三方登录,当你的网站接入了 - [OAuth 2.0 的四种方式](http://www.ruanyifeng.com/blog/2019/04/oauth-grant-types.html) - [GitHub OAuth 第三方登录示例教程](http://www.ruanyifeng.com/blog/2019/04/github-oauth.html) +## 8 什么是 SSO? + +SSO(Single Sign On)即单点登录说的是用户登陆多个子系统的其中一个就有权访问与其相关的其他系统。举个例子我们在登陆了京东金融之后,我们同时也成功登陆京东的京东超市、京东家电等子系统。 + +## 9.SSO与OAuth2.0的区别 + +OAuth 是一个行业的标准授权协议,主要用来授权第三方应用获取有限的权限。SSO解决的是一个公司的多个相关的自系统的之间的登陆问题比如京东旗下相关子系统京东金融、京东超市、京东家电等等。 + ## 参考 - https://medium.com/@sherryhsu/session-vs-token-based-authentication-11a6c5ac45e4 diff --git a/docs/system-design/authority-certification/sso.md b/docs/system-design/authority-certification/sso.md new file mode 100644 index 0000000000000000000000000000000000000000..a2042c6191319fc6504f659b6e75f70292ae484c --- /dev/null +++ b/docs/system-design/authority-certification/sso.md @@ -0,0 +1,125 @@ + + +> 本文授权转载自 : https://ken.io/note/sso-design-implement 作者:ken.io +> +> 相关推荐阅读:**[系统的讲解 - SSO单点登录](https://www.imooc.com/article/286710)** + +## 一、前言 + +### 1、SSO说明 + +SSO英文全称Single Sign On,单点登录。SSO是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统。https://baike.baidu.com/item/SSO/3451380 + +例如访问在网易账号中心(http://reg.163.com/ )登录之后 +访问以下站点都是登录状态 + +- 网易直播 [http://v.163.com](http://v.163.com/) +- 网易博客 [http://blog.163.com](http://blog.163.com/) +- 网易花田 [http://love.163.com](http://love.163.com/) +- 网易考拉 [https://www.kaola.com](https://www.kaola.com/) +- 网易Lofter [http://www.lofter.com](http://www.lofter.com/) + +### 2、单点登录系统的好处 + +1. **用户角度** :用户能够做到一次登录多次使用,无需记录多套用户名和密码,省心。 +2. **系统管理员角度** : 管理员只需维护好一个统一的账号中心就可以了,方便。 +3. **新系统开发角度:** 新系统开发时只需直接对接统一的账号中心即可,简化开发流程,省时。 + +### 3、设计目标 + +本篇文章也主要是为了探讨如何设计&实现一个SSO系统 + +以下为需要实现的核心功能: + +- 单点登录 +- 单点登出 +- 支持跨域单点登录 +- 支持跨域单点登出 + +## 二、SSO设计与实现 + +### 1、核心应用与依赖 + +![单点登录(SSO)设计](https://img.ken.io/blog/sso/sso-system.png-kblb.png) + +| 应用/模块/对象 | 说明 | +| ---------------- | ----------------------------------- | +| 前台站点 | 需要登录的站点 | +| SSO站点-登录 | 提供登录的页面 | +| SSO站点-登出 | 提供注销登录的入口 | +| SSO服务-登录 | 提供登录服务 | +| SSO服务-登录状态 | 提供登录状态校验/登录信息查询的服务 | +| SSO服务-登出 | 提供用户注销登录的服务 | +| 数据库 | 存储用户账户信息 | +| 缓存 | 存储用户的登录信息,通常使用Redis | + +### 2、用户登录状态的存储与校验 + +常见的Web框架对于[Session](https://ken.io/note/session-principle-skill)的实现都是生成一个SessionId存储在浏览器Cookie中。然后将Session内容存储在服务器端内存中,这个 ken.io 在之前[Session工作原理](https://ken.io/note/session-principle-skill)中也提到过。整体也是借鉴这个思路。 +用户登录成功之后,生成AuthToken交给客户端保存。如果是浏览器,就保存在Cookie中。如果是手机App就保存在App本地缓存中。本篇主要探讨基于Web站点的SSO。 +用户在浏览需要登录的页面时,客户端将AuthToken提交给SSO服务校验登录状态/获取用户登录信息 + +对于登录信息的存储,建议采用Redis,使用Redis集群来存储登录信息,既可以保证高可用,又可以线性扩充。同时也可以让SSO服务满足负载均衡/可伸缩的需求。 + +| 对象 | 说明 | +| --------- | ------------------------------------------------------------ | +| AuthToken | 直接使用UUID/GUID即可,如果有验证AuthToken合法性需求,可以将UserName+时间戳加密生成,服务端解密之后验证合法性 | +| 登录信息 | 通常是将UserId,UserName缓存起来 | + +### 3、用户登录/登录校验 + +- 登录时序图 + +![SSO系统设计-登录时序图](https://img.ken.io/blog/sso/sso-login-sequence.png-kbrb.png) + +按照上图,用户登录后Authtoken保存在Cookie中。 domian= test. com +浏览器会将domain设置成 .test.com, +这样访问所有*.test.com的web站点,都会将Authtoken携带到服务器端。 +然后通过SSO服务,完成对用户状态的校验/用户登录信息的获取 + +- 登录信息获取/登录状态校验 + +![SSO系统设计-登录信息获取/登录状态校验](https://img.ken.io/blog/sso/sso-logincheck-sequence.png-kbrb.png) + +### 4、用户登出 + +用户登出时要做的事情很简单: + +1. 服务端清除缓存(Redis)中的登录状态 +2. 客户端清除存储的AuthToken + +- 登出时序图 + +![SSO系统设计-用户登出](https://img.ken.io/blog/sso/sso-logout-sequence.png-kbrb.png) + +### 5、跨域登录、登出 + +前面提到过,核心思路是客户端存储AuthToken,服务器端通过Redis存储登录信息。由于客户端是将AuthToken存储在Cookie中的。所以跨域要解决的问题,就是如何解决Cookie的跨域读写问题。 + +> **Cookie是不能跨域的** ,比如我一个 + +解决跨域的核心思路就是: + +- 登录完成之后通过回调的方式,将AuthToken传递给主域名之外的站点,该站点自行将AuthToken保存在当前域下的Cookie中。 +- 登出完成之后通过回调的方式,调用非主域名站点的登出页面,完成设置Cookie中的AuthToken过期的操作。 +- 跨域登录(主域名已登录) + +![SSO系统设计-跨域登录(主域名已登录)](https://img.ken.io/blog/sso/sso-crossdomain-login-loggedin-sequence.png-kbrb.png) + +- 跨域登录(主域名未登录) + +![SSO系统设计-跨域登录(主域名未登录)](https://img.ken.io/blog/sso/sso-crossdomain-login-unlogin-sequence.png-kbrb.png) + +- 跨域登出 + +![SSO系统设计-跨域登出](https://img.ken.io/blog/sso/sso-crossdomain-logout-sequence.png-kbrb.png) + +## 三、备注 + +- 关于方案 + +这次设计方案更多是提供实现思路。如果涉及到APP用户登录等情况,在访问SSO服务时,增加对APP的签名验证就好了。当然,如果有无线网关,验证签名不是问题。 + +- 关于时序图 + +时序图中并没有包含所有场景,ken.io只列举了核心/主要场景,另外对于一些不影响理解思路的消息能省就省了。 \ No newline at end of file diff --git a/docs/system-design/data-communication/summary.md b/docs/system-design/data-communication/summary.md deleted file mode 100644 index 209df6b6493bc62951d89952049be9b8544b1109..0000000000000000000000000000000000000000 --- a/docs/system-design/data-communication/summary.md +++ /dev/null @@ -1,100 +0,0 @@ -> ## RPC - -**RPC(Remote Procedure Call)—远程过程调用** ,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议。RPC协议假定某些传输协议的存在,如TCP或UDP,为通信程序之间携带信息数据。在OSI网络通信模型中,RPC跨越了传输层和应用层。RPC使得开发分布式程序就像开发本地程序一样简单。 - -**RPC采用客户端(服务调用方)/服务器端(服务提供方)模式,** 都运行在自己的JVM中。客户端只需要引入要使用的接口,接口的实现和运行都在服务器端。RPC主要依赖的技术包括序列化、反序列化和数据传输协议,这是一种定义与实现相分离的设计。 - -**目前Java使用比较多的RPC方案主要有RMI(JDK自带)、Hessian、Dubbo以及Thrift等。** - -**注意: RPC主要指内部服务之间的调用,RESTful也可以用于内部服务之间的调用,但其主要用途还在于外部系统提供服务,因此没有将其包含在本知识点内。** - -### 常见RPC框架: - -- **RMI(JDK自带):** JDK自带的RPC - - 详细内容可以参考:[从懵逼到恍然大悟之Java中RMI的使用](https://blog.csdn.net/lmy86263/article/details/72594760) - -- **Dubbo:** Dubbo是 阿里巴巴公司开源的一个高性能优秀的服务框架,使得应用可通过高性能的 RPC 实现服务的输出和输入功能,可以和 Spring框架无缝集成。 - - 详细内容可以参考: - - - [ 高性能优秀的服务框架-dubbo介绍](https://blog.csdn.net/qq_34337272/article/details/79862899) - - - [Dubbo是什么?能做什么?](https://blog.csdn.net/houshaolin/article/details/76408399) - - -- **Hessian:** Hessian是一个轻量级的remotingonhttp工具,使用简单的方法提供了RMI的功能。 相比WebService,Hessian更简单、快捷。采用的是二进制RPC协议,因为采用的是二进制协议,所以它很适合于发送二进制数据。 - - 详细内容可以参考: [Hessian的使用以及理解](https://blog.csdn.net/sunwei_pyw/article/details/74002351) - -- **Thrift:** Apache Thrift是Facebook开源的跨语言的RPC通信框架,目前已经捐献给Apache基金会管理,由于其跨语言特性和出色的性能,在很多互联网公司得到应用,有能力的公司甚至会基于thrift研发一套分布式服务框架,增加诸如服务注册、服务发现等功能。 - - - 详细内容可以参考: [【Java】分布式RPC通信框架Apache Thrift 使用总结](https://www.cnblogs.com/zeze/p/8628585.html) - -### 如何进行选择: - -- **是否允许代码侵入:** 即需要依赖相应的代码生成器生成代码,比如Thrift。 -- **是否需要长连接获取高性能:** 如果对于性能需求较高的haul,那么可以果断选择基于TCP的Thrift、Dubbo。 -- **是否需要跨越网段、跨越防火墙:** 这种情况一般选择基于HTTP协议的Hessian和Thrift的HTTP Transport。 - -此外,Google推出的基于HTTP2.0的gRPC框架也开始得到应用,其序列化协议基于Protobuf,网络框架使用的是Netty4,但是其需要生成代码,可扩展性也比较差。 - -> ## 消息中间件 - -**消息中间件,也可以叫做中央消息队列或者是消息队列(区别于本地消息队列,本地消息队列指的是JVM内的队列实现)**,是一种独立的队列系统,消息中间件经常用来解决内部服务之间的 **异步调用问题** 。请求服务方把请求队列放到队列中即可返回,然后等待服务提供方去队列中获取请求进行处理,之后通过回调等机制把结果返回给请求服务方。 - -异步调用只是消息中间件一个非常常见的应用场景。此外,常用的消息队列应用场景还有如下几个: -- **解耦 :** 一个业务的非核心流程需要依赖其他系统,但结果并不重要,有通知即可。 -- **最终一致性 :** 指的是两个系统的状态保持一致,可以有一定的延迟,只要最终达到一致性即可。经常用在解决分布式事务上。 -- **广播 :** 消息队列最基本的功能。生产者只负责生产消息,订阅者接收消息。 -- **错峰和流控** - - -具体可以参考: - -[《消息队列深入解析》](https://blog.csdn.net/qq_34337272/article/details/80029918) - -当前使用较多的消息队列有ActiveMQ(性能差,不推荐使用)、RabbitMQ、RocketMQ、Kafka等等,我们之前提到的redis数据库也可以实现消息队列,不过不推荐,redis本身设计就不是用来做消息队列的。 - -- **ActiveMQ:** ActiveMQ是Apache出品,最流行的,能力强劲的开源消息总线。ActiveMQ是一个完全支持JMS1.1和J2EE 1.4规范的JMSProvider实现,尽管JMS规范出台已经是很久的事情了,但是JMS在当今的J2EE应用中间仍然扮演着特殊的地位。 - - 具体可以参考: - - [《消息队列ActiveMQ的使用详解》](https://blog.csdn.net/qq_34337272/article/details/80031702) - -- **RabbitMQ:** RabbitMQ 是一个由 Erlang 语言开发的 AMQP 的开源实现。RabbitMQ 最初起源于金融系统,用于在分布式系统中存储转发消息,在易用性、扩展性、高可用性等方面表现不俗 - > AMQP :Advanced Message Queue,高级消息队列协议。它是应用层协议的一个开放标准,为面向消息的中间件设计,基于此协议的客户端与消息中间件可传递消息,并不受产品、开发语言等条件的限制。 - - - 具体可以参考: - - [《消息队列之 RabbitMQ》](https://www.jianshu.com/p/79ca08116d57) - -- **RocketMQ:** - - 具体可以参考: - - [《RocketMQ 实战之快速入门》](https://www.jianshu.com/p/824066d70da8) - - [《十分钟入门RocketMQ》](http://jm.taobao.org/2017/01/12/rocketmq-quick-start-in-10-minutes/) (阿里中间件团队博客) - - -- **Kafka**:Kafka是一个分布式的、可分区的、可复制的、基于发布/订阅的消息系统(现在官方的描述是“一个分布式流平台”),Kafka主要用于大数据领域,当然在分布式系统中也有应用。目前市面上流行的消息队列RocketMQ就是阿里借鉴Kafka的原理、用Java开发而得。 - - 具体可以参考: - - [《Kafka应用场景》](http://book.51cto.com/art/201801/565244.htm) - - [《初谈Kafka》](https://mp.weixin.qq.com/s?__biz=MzU4NDQ4MzU5OA==&mid=2247484106&idx=1&sn=aa1999895d009d91eb3692a3e6429d18&chksm=fd9854abcaefddbd1101ca5dc2c7c783d7171320d6300d9b2d8e68b7ef8abd2b02ea03e03600#rd) - -**推荐阅读:** - -[《Kafka、RabbitMQ、RocketMQ等消息中间件的对比 —— 消息发送性能和区别》](https://mp.weixin.qq.com/s?__biz=MzU5OTMyODAyNg==&mid=2247484721&idx=1&sn=11e4e29886e581dd328311d308ccc068&chksm=feb7d144c9c058529465b02a4e26a25ef76b60be8984ace9e4a0f5d3d98ca52e014ecb73b061&scene=21#wechat_redirect) - - - - - - -