diff --git a/docusaurus.config.js b/docusaurus.config.js index e7bc7fe8..b5ea83c8 100644 --- a/docusaurus.config.js +++ b/docusaurus.config.js @@ -316,7 +316,7 @@ const config = { theme: lightCodeTheme, darkTheme: darkCodeTheme, defaultLanguage: "markdown", - additionalLanguages: ["java", "git","nginx"], + additionalLanguages: ["java", "git","nginx","http"], }, }), }; diff --git a/templates/文档 - 快速模板.md b/templates/文档 - 快速模板.md index 146507cc..51b2d656 100644 --- a/templates/文档 - 快速模板.md +++ b/templates/文档 - 快速模板.md @@ -5,8 +5,7 @@ keywords: - 关键字 tags: - 标签 +sidebar_position: 1 author: 7Wate date: <% tp.date.now("YYYY-MM-DD") %> --- - -一篇文档 - 快速模板 \ No newline at end of file diff --git a/wiki/safe/系统权限/权限设计方案/_category_.json b/wiki/safe/系统权限/权限设计方案/_category_.json new file mode 100644 index 00000000..a1ebca99 --- /dev/null +++ b/wiki/safe/系统权限/权限设计方案/_category_.json @@ -0,0 +1,8 @@ +{ + "label": "权限设计方案", + "position": 2, + "link": { + "type": "generated-index", + "title": "权限设计方案" + } +} \ No newline at end of file diff --git a/wiki/safe/权限控制/主流权限系统的设计.md b/wiki/safe/系统权限/权限设计方案/主流权限系统的设计.md similarity index 70% rename from wiki/safe/权限控制/主流权限系统的设计.md rename to wiki/safe/系统权限/权限设计方案/主流权限系统的设计.md index 96b56015..4b5c07c2 100644 --- a/wiki/safe/权限控制/主流权限系统的设计.md +++ b/wiki/safe/系统权限/权限设计方案/主流权限系统的设计.md @@ -14,39 +14,39 @@ data: 2022年08月08日 - **ABAC模型**:基于属性的访问控制 - **RBAC模型**:基于角色的权限访问控制 -## ACL模型:访问控制列表 +## ACL 模型:访问控制列表 -**Access Control List**,ACL是最早的、最基本的一种访问控制机制,是基于客体进行控制的模型,在其他模型中也有ACL的身影。为了解决相同权限的用户挨个配置的问题,后来也采用了用户组的方式。 +**Access Control List**,ACL 是最早的、最基本的一种访问控制机制,是基于客体进行控制的模型,在其他模型中也有 ACL 的身影。为了解决相同权限的用户挨个配置的问题,后来也采用了用户组的方式。 **原理**:每一个客体都有一个列表,列表中记录的是哪些主体可以对这个客体做哪些行为,非常简单。 -**例如**:当用户A要对一篇文章进行编辑时,ACL会先检查一下文章编辑功能的控制列表中有没有用户A,有就可以编辑,无则不能编辑。再例如:不同等级的会员在产品中可使用的功能范围不同。 +**例如**:当用户A要对一篇文章进行编辑时,ACL 会先检查一下文章编辑功能的控制列表中有没有用户 A,有就可以编辑,无则不能编辑。再例如:不同等级的会员在产品中可使用的功能范围不同。 **缺点**:当主体的数量较多时,配置和维护工作就会成本大、易出错。 -## DAC模型:自主访问控制 +## DAC 模型:自主访问控制 -Discretionary Access Control,DAC是ACL的一种拓展。 +Discretionary Access Control,DAC 是 ACL 的一种拓展。 -**原理**:在ACL模型的基础上,允许主体可以将自己拥有的权限自主地授予其他主体,所以权限可以任意传递。 +**原理**:在 ACL 模型的基础上,允许主体可以将自己拥有的权限自主地授予其他主体,所以权限可以任意传递。 -**例如**:常见于文件系统,LINUX,UNIX、WindowsNT版本的操作系统都提供DAC的支持。 +**例如**:常见于文件系统,LINUX,UNIX、WindowsNT 版本的操作系统都提供 DAC 的支持。 **缺点**:对权限控制比较分散,例如无法简单地将一组文件设置统一的权限开放给指定的一群用户。主体的权限太大,无意间就可能泄露信息。 -## MAC模型:强制访问控制 +## MAC 模型:强制访问控制 -**Mandatory Access Control**,MAC模型中主要的是双向验证机制。常见于机密机构或者其他等级观念强烈的行业,如军用和市政安全领域的软件。 +**Mandatory Access Control**,MAC 模型中主要的是双向验证机制。常见于机密机构或者其他等级观念强烈的行业,如军用和市政安全领域的软件。 **原理**:主体有一个权限标识,客体也有一个权限标识,而主体能否对该客体进行操作取决于双方的权限标识的关系。 -**例如**:将军分为上将>中将>少将,军事文件保密等级分为绝密>机密>秘密,规定不同军衔仅能访问不同保密等级的文件,如少将只能访问秘密文件;当某一账号访问某一文件时,系统会验证账号的军衔,也验证文件的保密等级,当军衔和保密等级相对应时才可以访问。 +**例如**:将军分为上将 > 中将 > 少将,军事文件保密等级分为绝密 > 机密 > 秘密,规定不同军衔仅能访问不同保密等级的文件,如少将只能访问秘密文件;当某一账号访问某一文件时,系统会验证账号的军衔,也验证文件的保密等级,当军衔和保密等级相对应时才可以访问。 **缺点**:控制太严格,实现工作量大,缺乏灵活性。 -## ABAC模型:基于属性的访问控制 +## ABAC 模型:基于属性的访问控制 -**Attribute-Based Access Control**,能很好地解决RBAC的缺点,在新增资源时容易维护。 +**Attribute-Based Access Control**,能很好地解决 RBAC 的缺点,在新增资源时容易维护。 **原理**:通过动态计算一个或一组属性是否满足某种机制来授权,是一种很灵活的权限模型,可以按需实现不同颗粒度的权限控制。 @@ -57,7 +57,7 @@ Discretionary Access Control,DAC是ACL的一种拓展。 3. 环境属性,即空间限制、时间限制、频度限制; 4. 操作属性,即行为类型,如读写、只读等。 -**例如**:早上9:00,11:00期间A、B两个部门一起以考生的身份考试,下午14:00,17:00期间A、B两个部门相互阅卷。 +**例如**:早上 9:00,11:00 期间 A、B 两个部门一起以考生的身份考试,下午 14:00,17:00 期间 A、B 两个部门相互阅卷。 **缺点**:规则复杂,不易看出主体与客体之间的关系,实现非常难,现在应用的很少。 @@ -65,13 +65,13 @@ Discretionary Access Control,DAC是ACL的一种拓展。 **Role-Based Access Control**,核心在于用户只和角色关联,而角色代表对了权限,是一系列权限的集合。 -RBAC三要素: +RBAC 三要素: 1. **用户**:系统中所有的账户 2. **角色**:一系列权限的集合(如:管理员,开发者,审计管理员等) 3. **权限**:菜单,按钮,数据的增删改查等详细权限。 -在**RBAC**中,权限与角色相关联,用户通过成为适当角色的成员而得到这些角色的权限。 +在 **RBAC **中,权限与角色相关联,用户通过成为适当角色的成员而得到这些角色的权限。 角色是为了完成各种工作而创造,用户则依据它的责任和资格来被指派相应的角色,用户可以很容易地从一个角色被指派到另一个角色。 @@ -79,51 +79,51 @@ RBAC三要素: **优点**:便于角色划分,更灵活的授权管理;最小颗粒度授权; -![基于角色的权限控制](https://static.7wate.com/img/2022/08/08/e11745fdd5e0f.png) +![RBAC](https://static.7wate.com/img/2022/08/30/2fb0d9ad61795.png) ## RBAC的深度拓展 -RBAC模型可以分为:**RBAC0**、**RBAC1**、**RBAC2**、**RBAC3** 四个阶段,一般公司使用**RBAC0**的模型就可以。另外,**RBAC0**相当于底层逻辑,后三者都是在**RBAC0**模型上的拔高。 +RBAC模型可以分为:**RBAC0**、**RBAC1**、**RBAC2**、**RBAC3** 四个阶段,一般公司使用 **RBAC0** 的模型就可以。另外,**RBAC0** 相当于底层逻辑,后三者都是在 **RBAC0** 模型上的拔高。 我先简单介绍下这四个RBAC模型: -### 1. RBAC0模型 +### 1. RBAC0 模型 用户和角色、角色和权限多对多关系。 简单来说就是一个用户拥有多个角色,一个角色可以被多个用户拥有,这是用户和角色的多对多关系;同样的,角色和权限也是如此。 -**RBAC0**模型如下图:没有画太多线,但是已经能够看出多对多关系。 +**RBAC0** 模型如下图:没有画太多线,但是已经能够看出多对多关系。 -![RBAC0](https://static.7wate.com/img/2022/08/08/cf466dbdf2bcd.png) +![RBAC0](https://static.7wate.com/img/2022/08/30/704178e086081.png) -### 2. RBAC1模型 +### 2. RBAC1 模型 -相对于**RBAC0**模型,增加了**角色分级**的逻辑,类似于树形结构,下一节点继承上一节点的所有权限,如**role1**根节点下有**role1.1**和**role1.2**两个子节点 +相对于 **RBAC0 **模型,增加了**角色分级**的逻辑,类似于树形结构,下一节点继承上一节点的所有权限,如 **role1** 根节点下有 **role1.1** 和 **role1.2** 两个子节点 -![RBAC1](https://static.7wate.com/img/2022/08/08/ca7afbb3e8cac.png) +![RABC1](https://static.7wate.com/img/2022/08/30/ab50d1c150699.png) -角色分级的逻辑可以有效的规范角色创建(主要得益于权限继承逻辑),我之前做过BD工具(类CRM),BD之间就有分级(经理、主管、专员),如果采用RBAC0模型做权限系统,我可能需要为经理、主管、专员分别创建一个角色(角色之间权限无继承性),极有可能出现一个问题,由于权限配置错误,主管拥有经理都没有权限。 +角色分级的逻辑可以有效的规范角色创建(主要得益于权限继承逻辑),我之前做过 BD 工具(类 CRM ),BD 之间就有分级(经理、主管、专员),如果采用 RBAC0 模型做权限系统,我可能需要为经理、主管、专员分别创建一个角色(角色之间权限无继承性),极有可能出现一个问题,由于权限配置错误,主管拥有经理都没有权限。 -而RBAC1模型就很好解决了这个问题,创建完经理角色并配置好权限后,主管角色的权限继承经理角色的权限,并且支持针对性删减主管权限。 +而 RBAC1 模型就很好解决了这个问题,创建完经理角色并配置好权限后,主管角色的权限继承经理角色的权限,并且支持针对性删减主管权限。 -### 3. RBAC2模型 +### 3. RBAC2 模型 -基于**RBAC0**模型,对角色增加了更多约束条件。 +基于 **RBAC0** 模型,对角色增加了更多约束条件。 -![RBAC2](https://static.7wate.com/img/2022/08/08/83e2b3f4e2f85.png) +![RBAC2](https://static.7wate.com/img/2022/08/30/adc688e2b7f77.png) 如**角色互斥**,比较经典的案例是财务系统中出纳不得兼管稽核,那么在赋予财务系统操作人员角色时,同一个操作员不能同时拥有出纳和稽核两个角色。 -如**角色数量限制**,例如:一个角色专门为公司CEO创建的,最后发现公司有10个人拥有CEO角色,一个公司有10个CEO?这就是对角色数量的限制,它指的是有多少用户能拥有这个角色。 +如**角色数量限制**,例如:一个角色专门为公司 CEO 创建的,最后发现公司有 10 个人拥有 CEO 角色,一个公司有10 个 CEO ?这就是对角色数量的限制,它指的是有多少用户能拥有这个角色。 **RBAC2** 模型主要是为了增加角色赋予的限制条件,这也符合权限系统的目标:权责明确,系统使用安全、保密。 ### 4. RBAC3模型 -同样是基于**RBAC0**模型,但是综合了**RBAC1**和**RBAC2**的所有特点 +同样是基于 **RBAC0** 模型,但是综合了 **RBAC1** 和 **RBAC2** 的所有特点 -这里就不在多描述,读者返回去看**RBAC1**和**RBAC2**模型的描述即可。 +这里就不在多描述,读者返回去看 **RBAC1** 和 **RBAC2** 模型的描述即可。 ## RBAC 权限管理的在实际系统中的应用 @@ -135,15 +135,15 @@ RBAC 权限模型由三大部分构成,即**用户管理**、**角色管理** 权限管理是前两种管理的再加固,做太细容易太碎片,做太粗又不够安全,这里我们需要根据经验和实际情况来设计。 -### 1.用户管理 +### 1. 用户管理 用户管理中的用户,是企业里每一位员工,他们本身就有自己的组织架构,我们可以直接使用企业部门架构或者业务线架构来作为线索,构建用户管理系统。 -![用户管理](https://static.7wate.com/img/2022/08/08/71d1e4799cbf1.png) +![用户管理系统](https://static.7wate.com/img/2022/08/30/887a6f017f7e3.png) **需要特殊注意**:实际业务中的组织架构可能与企业部门架构、业务线架构不同,需要考虑数据共享机制,一般的做法为授权某个人、某个角色组共享某个组织层级的某个对象组数据。 -### 2.角色管理 +### 2. 角色管理 在设计系统角色时,我们应该深入理解公司架构、业务架构后,再根据需求设计角色及角色内的等级。 @@ -177,7 +177,7 @@ RBAC 权限模型由三大部分构成,即**用户管理**、**角色管理** 权限管理一般从三个方面来做限制。**页面/菜单权限**,**操作权限**,**数据权限**。 -![权限管理](https://static.7wate.com/img/2022/08/08/880d2c1254732.png) +![权限管理系统](https://static.7wate.com/img/2022/08/30/8ad6abcc85524.png) #### 1. 页面/菜单权限 @@ -193,7 +193,7 @@ RBAC 权限模型由三大部分构成,即**用户管理**、**角色管理** #### 4. 数据权限如何管控 -数据权限可以分为行权限和列权限。行权限控制:看多少条数据。列权限控制:看一条数据的多少个字段 +数据权限可以分为行权限和列权限。行权限控制:看多少条数据。列权限控制:看一条数据的多少个字段。 简单系统中可以通过组织架构来管控行权限,按照角色来配置列权限,但是遇到复杂情况,组织架构是承载不了复杂行权限管控,角色也更不能承载列的特殊化展示。 @@ -205,18 +205,18 @@ RBAC 权限模型由三大部分构成,即**用户管理**、**角色管理** ## 用户管理系统权限设计中的更多实践细节 -### 1.超级管理员 +### 1. 超级管理员 超级管理员是用来启动系统,配置系统的账号。这个账号应该在配置好系统,创建管理员之后被隐藏起来。超级管理员账号拥有系统中全部权限,可穿梭查看各部门数据,如果使用不恰当,是系统管理的安全隐患。 -### 2.互斥角色如何处理 +### 2. 互斥角色如何处理 当用户已经有用的角色和即将添加的角色互相互斥时,应该在添加新角色时,提示管理员因角色互斥的原因,无法进行新角色添加。如需添加,要先撤销掉前一个角色,再添加新角色。 -### 3.用户管理权限系统设计一定要简单清晰 +### 3. 用户管理权限系统设计一定要简单清晰 在设计权限系统之处,一定要理清思路,一切从简,能不增加的多余角色和权限逻辑,就一定不要增加。因为随着公司业务的扩大,权限和角色也会随之增多,如果初期设计思路不严谨,那么权限系统会随着业务的扩大而无限混乱下去,此时再来整理权限,已经太晚了。所以初期设计就一定要条理清晰,简单明了,能避免后续非常多不必要的麻烦。 -### 4.无权提示页 +### 4. 无权提示页 有时员工 A 会直接给员工 B 分享他当下正在操作的页面,但有可能员工 B 无权查看。此时我们应该在这里考虑添加「无权提示页」,避免粗暴的 404 页面让员工 B 以为是系统出错了。 diff --git a/wiki/safe/系统权限/系统权限简明指南.md b/wiki/safe/系统权限/系统权限简明指南.md new file mode 100644 index 00000000..c474dd0f --- /dev/null +++ b/wiki/safe/系统权限/系统权限简明指南.md @@ -0,0 +1,52 @@ +--- +title: 系统权限简明指南 +description: 系统权限简明指南 +keywords: +- 系统 +- 权限 +tags: +- 安全 +sidebar_position: 1 +author: 7Wate +date: 2022-08-31 +--- + +## 认证 + +**认证(Identification)**是指根据声明者所特有的识别信息,确认声明者的身份。**你需要用身份证证明你自己是你自己**。比如我们常见的认证技术:身份证、用户名和密码、用户手机:手机短信、手机二维码扫描、手势密码、电子邮箱、指纹、语音、眼睛虹膜、大数据识别等等 + +## 授权 + +**授权(Authorization)**在信息安全领域是指**资源所有者**委派**执行者**,赋予**执行者**指定范围的资源操作权限,以便对资源的相关操作。 + +- **现实生活领域**:银行卡(由银行派发)、门禁卡(由物业管理处派发)、钥匙(由房东派发),这些都是现实生活中授权的实现方式。 + +- **互联网领域**: Web 服务器的 Session 机制、Web 浏览器的 Cookie 机制、颁发授权令牌(Token)等都是一个授权的机制。 + +## 鉴权 + +**鉴权(Authentication)**在信息安全领域是指**对于一个声明者所声明的身份权利,对其所声明的真实性进行鉴别确认的过程**。若从授权出发,则会更加容易理解鉴权。授权和鉴权是两个上下游相匹配的关系:**先授权,后鉴权**。 + +- **现实生活领域:** 门禁卡需要通过门禁卡识别器,银行卡需要通过银行卡识别器; + +- **互联网领域:** 校验 Session / Cookie / Token 的合法性和有效性 + +**鉴权**是一个承上启下的一个环节,上游它接受授权的输出,校验其真实性后,然后获取权限(Permission),这个将会为下一步的权限控制做好准备。 + +## 权限控制 + +**权限控制(Access/Permission Control)** 将可执行的操作定义为权限列表,然后判断操作是否允许/禁止。对于权限控制,可以分为两部分进行理解:一个是**权限**,另一个是**控制**。**权限是抽象的逻辑概念,而控制是具体的实现方式。** + +- **现实生活领域:** 以门禁卡的权限实现为例,一个门禁卡,拥有开公司所有的门的权限;一个门禁卡,拥有管理员角色的权限,因而可以开公司所有的门。 + +- **互联网领域:** 通过 Web 后端服务,来控制接口访问,允许或拒绝访问请求。 + +## 认证、授权、鉴权和权限控制的关系? + +![关系](https://static.7wate.com/img/2022/08/29/05d140d5e8751.png) + +**认证**、**授权**、**鉴权**和**权限控制**,这四个环节是一个**前后依次发生**、**上下游**的关系;需要说明的是,这四个环节在有些时候会同时发生。 例如在下面的几个场景: + +- **使用门禁卡开门:** 认证、授权、鉴权、权限控制四个环节一气呵成,在瞬间同时发生。 + +- **用户的网站登录:** 用户在使用用户名和密码进行登录时,认证和授权两个环节一同完成,而鉴权和权限控制则发生在后续的请求访问中,比如在选购物品或支付时。 diff --git a/wiki/safe/系统权限/鉴权解决方案/HTTP 基本鉴权.md b/wiki/safe/系统权限/鉴权解决方案/HTTP 基本鉴权.md new file mode 100644 index 00000000..355122f2 --- /dev/null +++ b/wiki/safe/系统权限/鉴权解决方案/HTTP 基本鉴权.md @@ -0,0 +1,74 @@ +--- +title: HTTP 基本鉴权 +description: HTTP 基本鉴权 +keywords: +- HTTP +- 鉴权 +tags: +- 权限 +sidebar_position: 1 +author: 7Wate +date: 2022-08-31 +--- +## HTTP 基本鉴权 + +在 HTTP 中,**基本认证方案(Basic Access Authentication)**是允许客户端(通常指的就是网页浏览器)在请求时,通过用户提供用户名和密码的方式,实现对用户身份的验证。 + +### 流程图 + +![认证流程图](https://static.7wate.com/img/2022/08/30/298b4e5cd922d.png) + +### 步骤解析 + +1. **客户端:** 向服务器请求一个**受限的列表数据或资源**。 + +```http + GET /list/ HTTP/1.1 + Host: www.baidu.com + Authorization: Basic aHR0cHdhdGNoOmY= +``` + +2. **服务器**:客户端你好,这个资源在安全区 baidu.com 里是受限资源,需要基本认证。并且向客户端返回 401 状态码 Unauthorized(未授权)以及附带提供了一个认证域 `www-Authenticate: Basic realm="baidu.com"` 要求进行身份验证;其中 Basic 就是验证的模式,而 `realm="baidu.com"` 说明客户端需要输入这个安全域的用户名和密码,而不是其他域的。 + +```http + HTTP/1.1 401 Unauthorized + www-Authenticate: Basic realm= "baidu.com" +``` + +3. **客户端:** 服务器,我已经携带了用户名和密码给你了,你看一下(如果客户端是浏览器,那么此时会自动弹出一个弹窗,让用户输入用户名和密码); + + 输入完用户名和密码后,则客户端将用户名及密码以 Base64 加密方式发送给服务器 + + 传送的格式如下(其中 Basic 内容为:**用户名+密码的 AES 64 形式**): + +```http + GET /list/ HTTP/1.1 + Authorization: Basic Ksid2FuZzp3YW5n== +``` + +4. **服务器:** 客户端你好,我已经校验了 `Authorization` 字段你的用户名和密码,是正确的,这是你要的资源。 + +```http + HTTP/1.1 200 OK + ... +``` + +### 优点 + +简单易用,基本所有流行的浏览器都支持。 + +### 缺点 + +#### 不安全 + +- 由于是基于 HTTP 传输,所以它在网络上几乎是裸奔的,虽然它使用了 Base64 来编码,但这个编码很容易就可以解码出来。 + +- 即使认证内容无法被解码为原始的用户名和密码也是不安全的,恶意用户可以再获取了认证内容后使用其不断的享服务器发起请求,这就是所谓的重放攻击。 + +#### 无法主动注销 + +- 由于 HTTP 协议没有提供机制清除浏览器中的 Basic 认证信息,除非标签页或浏览器关闭、或用户清除历史记录。 + +### 使用场景 + +内部网络,或者对安全要求不是很高的网络。 diff --git a/wiki/safe/系统权限/鉴权解决方案/JWT(JSON Web Token)鉴权.md b/wiki/safe/系统权限/鉴权解决方案/JWT(JSON Web Token)鉴权.md new file mode 100644 index 00000000..66263d67 --- /dev/null +++ b/wiki/safe/系统权限/鉴权解决方案/JWT(JSON Web Token)鉴权.md @@ -0,0 +1,105 @@ +--- +title: JWT 鉴权 +description: JWT 鉴权 +keywords: +- JWT +- Java +- 鉴权 +tags: +- 权限 +sidebar_position: 4 +author: 7Wate +date: 2022-08-31 +--- +## JWT(JSON Web Token)鉴权 + +通过第三节,我们知道了 Token 的使用方式以及组成,我们不难发现,服务端验证客户端发送过来的 Token 时,还需要查询数据库获取用户基本信息,然后验证 Token 是否有效;这样每次请求验证都要查询数据库,增加了查库带来的延迟等性能消耗。 + +**那么这时候业界常用的 JWT 就应运而生了!!!** + +### JWT 的定义 + +JWT 是 Auth0 提出的通过对 JSON 进行加密签名来实现授权验证的方案。 + +就是登录成功后将相关用户信息组成 JSON 对象,然后对这个对象进行某种方式的加密,返回给客户端; 客户端在下次请求时带上这个 Token; 服务端再收到请求时校验 token 合法性,其实也就是在校验请求的合法性。 + +### JWT 的组成 + +JWT 由三部分组成:**Header 头部**、**Payload 负载**和 **Signature 签名**。它是一个很长的字符串,中间用( . )分隔成三个部分。 + +```text +eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c +``` + +#### Header 头部 + +在 Header 中通常包含了两部分: + +- typ:代表 Token 的类型,这里使用的是 JWT 类型。 +- alg:使用的 Hash 算法,例如 HMAC SHA256 或 RSA。 + +```json +{ + "alg": "HS256", + "typ": "JWT" +} +``` + +#### Payload 负载 + +它包含一些声明 Claim(实体的描述,通常是一个 User 信息,还包括一些其他的元数据),用来存放实际需要传递的数据,JWT 规定了7个官方字段: + +- iss(issuer):签发人 +- exp(expiration time):过期时间 +- sub(subject):主题 +- aud(audience):受众 +- nbf(Not Before):生效时间 +- iat(Issued At):签发时间 +- jti(JWT ID):编号 + +除了官方字段,你还可以在这个部分定义私有字段,下面就是一个例子。 + +```json +{ + "sub": "1234567890", + "name": "John Doe", + "admin": true +} +``` + +#### Signature 签名 + +Signature 部分是对前两部分的签名,防止数据篡改。 + +首先,需要指定一个密钥(secret)。这个密钥只有服务器才知道,不能泄露给用户。然后,使用 Header 里面指定的签名算法(默认是 HMAC SHA256),按照下面的公式产生签名。 + +```java +HMACSHA256( + base64UrlEncode(header) + "." + + base64UrlEncode(payload), + secret) +``` + +### JWT 的使用方式 + +客户端收到服务器返回的 JWT,可以储存在 Cookie 里面,也可以储存在 localStorage。 + +此后,客户端每次与服务器通信,都要带上这个 JWT。你可以把它放在 Cookie 里面自动发送,但是这样不能跨域,所以更好的做法是放在 HTTP 请求的头信息 Authorization 字段里面。 + +```http + Authorization: Bearer +``` + +### JWT 的认证流程图 + +![JWT 的认证流程图](https://static.7wate.com/img/2022/08/30/d6666d37094db.png) + +### JWT 的优点 + +- 不需要在服务端保存会话信息(RESTful API 的原则之一就是无状态),所以易于应用的扩展,即信息不保存在服务端,不会存在 Session 扩展不方便的情况。 +- JWT 中的 Payload 负载可以存储常用信息,用于信息交换,有效地使用 JWT,可以降低服务端查询数据库的次数。 + +### JWT 的缺点 + +- **加密问题:** JWT 默认是不加密,但也是可以加密的;生成原始 Token 以后,可以用密钥再加密一次。 +- **到期问题:** 由于服务器不保存 Session 状态,因此无法在使用过程中废止某个 Token,或者更改 Token 的权限。一旦 JWT 签发了,在到期之前就会始终有效,除非服务器部署额外的逻辑。 diff --git a/wiki/safe/系统权限/鉴权解决方案/OAuth 鉴权.md b/wiki/safe/系统权限/鉴权解决方案/OAuth 鉴权.md new file mode 100644 index 00000000..77196fa9 --- /dev/null +++ b/wiki/safe/系统权限/鉴权解决方案/OAuth 鉴权.md @@ -0,0 +1,220 @@ +--- +title: OAuth 鉴权 +description: OAuth 鉴权 +keywords: +- OAuth +- 鉴权 +tags: +- 权限 +sidebar_position: 6 +author: 7Wate +date: 2022-08-31 +--- +## OAuth 2.0 + +OAuth 协议又有 1.0 和 2.0 两个版本,2.0 版整个授权验证流程更简单更安全,也是目前最主要的用户身份验证和授权方式。 + +### OAuth 2.0 定义 + +**OAuth** 是一个开放标准,允许用户授权第三方网站(例如 CSDN、思否等)获取用户数据。而不需要将用户名和密码提供给第三方网站;常见的提供 OAuth 认证服务的厂商: **支付宝、QQ、微信、微博。** + +简单说,**OAuth 就是一种授权机制。数据的所有者告诉系统,同意授权第三方应用进入系统并获取这些数据。系统从而产生一个短期的进入令牌(Token),用来代替密码,供第三方应用使用。** + +#### 令牌与密码的差异 + +令牌(Token)与密码(Password)的作用是一样的,都可以进入系统,但是有三点差异。 + +1. **令牌是短期的,到期会自动失效,**用户自己无法修改。密码一般长期有效,用户不修改,就不会发生变化。 +2. **令牌可以被数据所有者撤销,会立即失效。** +3. **令牌有权限范围(scope):** 对于网络服务来说,只读令牌就比读写令牌更安全。密码一般是完整权限。 + +OAuth 2.0 对于如何颁发令牌的细节,规定得非常详细。具体来说,一共分成**四种授权**模式 **(Authorization Grant)** ,适用于不同的互联网场景。 + +- 授权码(authorization-code) +- 隐藏式(implicit) +- 密码式(password): +- 客户端凭证(client credentials) + +无论哪个模式都拥有三个必要角色:**客户端**、**授权服务器**、**资源服务器**,有的还有**用户(资源拥有者)**。 + +## 授权码模式 + +**授权码(Authorization Code Grant) 方式,指的是第三方应用先申请一个授权码,然后再用该码获取令牌。** + +这种方式是最常用的流程,安全性也最高,它适用于那些有后端服务的 Web 应用。授权码通过前端传送,令牌则是储存在后端,而且所有与资源服务器的通信都在后端完成。这样的前后端分离,可以避免令牌泄漏。 + +一句话概括:**客户端换取授权码,客户端使用授权码换 Token,客户端使用 Token 访问资源**。 + +### 步骤详解 + +#### 1. 客户端 + +打开网站 A,点击登录按钮,请求 A 服务,A 服务重定向 (重定向地址如下) 至授权服务器(如QQ、微信授权服务)。 + +```http +https://qq.com/oauth/authorize? + response_type=code& + client_id=CLIENT_ID& + redirect_uri=CALLBACK_URL& + scope=read +``` + +上面 URL 中,response_type 参数表示要求返回授权码(code),client_id 参数让 B 知道是谁在请求,redirect_uri 参数是 B 接受或拒绝请求后的跳转网址,scope 参数表示要求的授权范围(这里是只读) + +![授权码模式](https://static.7wate.com/img/2022/08/30/cd507ff3bb9b9.png) + +#### 2. 授权服务器 + +授权服务网站会要求用户登录,然后询问是否同意给予 A 网站授权。用户表示同意,这时授权服务网站就会跳回 redirect_uri 参数指定的网址。跳转时,会传回一个授权码,就像下面这样,code 参数就是授权码。 + +```http +https://a.com/callback?code=AUTHORIZATION_CODE +``` + +![授权服务器](https://static.7wate.com/img/2022/08/30/e8a2a515684a0.png) + +#### 3. 网站 A 服务器 + +拿到授权码以后,就可以向 授权服务器 (qq.com) 请求令牌。 + +```http +https://qq.com/oauth/token? + client_id=CLIENT_ID& + client_secret=CLIENT_SECRET& + grant_type=authorization_code& + code=AUTHORIZATION_CODE& + redirect_uri=CALLBACK_URL +``` + +上面 URL 中,client_id 参数和 client_secret 参数用来让授权服务器 确认 A 的身份(client_secret 参数是保密的,因此只能在后端发请求),grant_type 参数的值是 AUTHORIZATION_CODE,表示采用的授权方式是授权码,code 参数是上一步拿到的授权码,redirect_uri 参数是令牌颁发后的回调网址。 + +![网站 A 服务器](https://static.7wate.com/img/2022/08/30/f75bff03879bd.png) + +#### 4. 授权服务器 + +收到请求以后,验证通过,就会颁发令牌;具体做法是向 redirect_uri 指定的网址,发送一段 JSON 数据。 + +```json +{ + "access_token":"ACCESS_TOKEN", + "token_type":"bearer", + "expires_in":2592000, + "refresh_token":"REFRESH_TOKEN", + "scope":"read", + "uid":100101, + "info":{...} +} +``` + +上面 JSON 数据中,access_token 字段就是令牌,A 网站在后端拿到了,然后返回给客户端即可。 + +![授权服务器](https://static.7wate.com/img/2022/08/30/e8a7b64693d3c.png) + +## 隐藏式模式(Implicit Grant) + +有些 Web 应用是纯前端应用,没有后端;这时就不能用上面的方式了,必须将令牌储存在前端。 + +OAuth2.0 就规定了**第二种方式,允许直接向前端颁发令牌。这种方式没有授权码这个中间步骤,所以称为(授权码)"隐藏式"(implicit)**。 + +一句话概括:**客户端让用户登录授权服务器换 Token,客户端使用 Token 访问资源。** + +### 步骤详解 + +#### 1. 客户端 + +打开网站 A,然后 A 网站提供一个链接,要求用户跳转到授权服务器,授权用户数据给 A 网站使用。 + +```http +https://qq.com/oauth/authorize? + response_type=token& + client_id=CLIENT_ID& + redirect_uri=CALLBACK_URL& + scope=read +``` + +上面 URL 中,response_type 参数为 token,表示要求直接返回令牌。 + +#### 2. 授权服务器 + +用户跳转到授权服务器,登录后同意给予 A 网站授权。这时,授权服务器就会跳回 redirect_uri 参数指定的跳转网址,并且把令牌作为 URL 参数,传给 A 网站。 + +```http +https://a.com/callback#token=ACCESS_TOKEN +``` + +上面 URL 中,token 参数就是令牌,A 网站因此直接在前端拿到令牌。 + +![授权服务器](https://static.7wate.com/img/2022/08/30/0e02abdb53ae8.png) + +还有需要**注意**的地方如下: + +1. 令牌的位置是 URL 锚点(fragment),而不是查询字符串(querystring),这是因为 OAuth 2.0 允许跳转网址是 HTTP 协议,因此存在"中间人攻击"的风险,而浏览器跳转时,锚点不会发到服务器,就减少了泄漏令牌的风险。 +2. 这种方式把令牌直接传给前端,是很不安全的。因此,只能用于一些安全要求不高的场景,并且令牌的有效期必须非常短,通常就是会话期间(session)有效,浏览器关掉,令牌就失效了。 + +## 用户名密码式模式(Password Credentials Grant) + +如果你高度信任某个应用,OAuth 2.0 也允许用户把用户名和密码,直接告诉该应用。该应用就使用你的密码,申请令牌,这种方式称为"密码式"(password)。 + +一句话概括:**用户在客户端提交账号密码换 Token,客户端使用 Token访问资源。** + +### 步骤详解 + +##### 1. 客户端 + +A 网站要求用户提供 授权服务器(qq.com)的用户名和密码。拿到以后,A 就直接向授权服务器请求令牌。 + +```http +https://oauth.b.com/token? + grant_type=password& + username=USERNAME& + password=PASSWORD& + client_id=CLIENT_ID +``` + +上面 URL 中,grant_type 参数是授权方式,这里的 password 表示"密码式",username 和 password 是授权服务器的用户名和密码。 + +##### 2. 授权服务器 + +授权服务器验证身份通过后,直接给出令牌。注意,这时不需要跳转,而是把令牌放在 JSON 数据里面,作为 HTTP 回应,A 网站因此拿到令牌。 + +这种方式需要用户给出自己的用户名/密码,显然风险很大,因此只适用于其他授权方式都无法采用的情况,而且必须是用户高度信任的应用。 + +## 客户端模式(Client Credentials Grant) + +客户端模式指客户端以自己的名义,而不是以用户的名义,向授权服务器进行认证。主要适用于没有前端的命令行应用。 + +一句话概括:**客户端使用自己的标识换token,客户端使用token访问资源**。 + +### 步骤详解 + +##### 1. 客户端 + +客户端向授权服务器进行身份认证,并要求一个访问令牌。 + +```http +https://oauth.b.com/token? + grant_type=client_credentials& + client_id=CLIENT_ID& + client_secret=CLIENT_SECRET +``` + +上面 URL 中,grant_type 参数等于 client_credentials 表示采用凭证式,client_id 和 client_secret 用来让授权服务器确认 A 的身份。 + +##### 2. 授权服务器 + +授权服务器验证通过以后,直接返回令牌。这种方式给出的令牌,是针对第三方应用的,而不是针对用户的,即有可能多个用户共享同一个令牌。 + +## 授权模式对比 + +按授权需要的多端情况: + +| 模式 | 需要前端 | 需要后端 | 需要用户响应 | 需要客户端密钥 | +| --------------------------------- | -------- | -------- | ------------ | -------------- | +| 授权码模式 Authorization Code | ✅ | ✅ | ✅ | ✅ | +| 隐式授权模式 Implicit Grant | ✅ | ❌ | ✅ | ❌ | +| 密码授权模式 Password Grant | ✅ | ✅ | ✅ | ✅ | +| 客户端授权模式 Client Credentials | ❌ | ✅ | ❌ | ✅ | + +## 授权模式分类 + +![按照客户端类型与访问令牌所有者分类](https://static.7wate.com/img/2022/08/30/aa101efbae0a2.png) diff --git a/wiki/safe/系统权限/鉴权解决方案/Session-Cookie 鉴权.md b/wiki/safe/系统权限/鉴权解决方案/Session-Cookie 鉴权.md new file mode 100644 index 00000000..9d30b9a4 --- /dev/null +++ b/wiki/safe/系统权限/鉴权解决方案/Session-Cookie 鉴权.md @@ -0,0 +1,106 @@ +--- +title: Session-Cookie 鉴权 +description: Session-Cookie 鉴权 +keywords: +- Session +- Cookie +- 鉴权 +tags: +- 权限 +sidebar_position: 2 +author: 7Wate +date: 2022-08-31 +--- +## Session-Cookie 鉴权 + +**Session-Cookie** 认证是利用服务端的 **Session(会话**)和 **浏览器(客户端)** 的 Cookie 来实现的前后端通信认证模式。 + +在理解这句话之前我们先简单了解下**什么是 Cookie**以及**什么是 Session** ? + +### Cookie 是什么 + +众所周知,**HTTP 是无状态的协议**(对于事务处理没有记忆能力,每次客户端和服务端会话完成时,服务端不会保存任何会话信息);所以为了让服务器区分不同的客户端,就必须主动的去维护一个状态,这个状态用于告知服务端前后两个请求是否来自同一浏览器,而这个状态可以通过 **Cookie** 去实现。 + +#### 特点 + +- Cookie 存储在客户端,可随意篡改,不安全。 + +- 有大小限制,最大为 4kb。 + +- 有数量限制,一般一个浏览器对于一个网站只能存不超过 20 个 Cookie,浏览器一般只允许存放 300个 Cookie。 + +- Android 和 IOS 对 Cookie 支持性不好。 + +- Cookie 是不可跨域的,但是一级域名和二级域名是允许共享使用的(靠的是 domain)。 + +### Session 是什么 + +Session 的抽象概念是会话,是无状态协议通信过程中,为了实现中断 / 继续操作,将用户和服务器之间的交互进行的一种抽象;具体来说,是服务器生成的一种 Session 结构,可以通过多种方式保存,如内存、数据库、文件等,大型网站一般有专门的 Session 服务器集群来保存用户会话; + +#### 流程 + +1. **客户端:** 用户向服务器首次发送请求。 + +2. **服务器:** 接收到数据并自动为该用户创建特定的 Session / Session ID,来标识用户并跟踪用户当前的会话过程。 + +3. **客户端:** 浏览器收到响应获取会话信息,并且会在下一次请求时带上 Session / Session ID。 + +4. **服务器:** 服务器提取后会与本地保存的 Session ID进行对比找到该特定用户的会话,进而获取会话状态。 + +5. 至此客户端与服务器的通信变成有状态的通信。 + +#### 特点 + +- Session 保存在服务器上。 + +- 通过服务器自带的加密协议进行。 + +### Session 与 Cookie 的差异 + +- **安全性:** Cookie 由于保存在客户端,可随意篡改;Session 则不同存储在服务器端,无法伪造。所以 Session 的安全性更高。 + +- **存取值的类型不同:** Cookie 只支持字符串数据;Session 可以存任意数据类型。 + +- **有效期不同:** Cookie 可设置为长时间保持;Session 一般失效时间较短。 + +- **存储大小不同:** Cookie 保存的数据不能超过 4K。 + +### Session-Cookie 的认证流程图 + +![Session-Cookie 的认证流程图](https://static.7wate.com/img/2022/08/30/50ad8c6cc6e96.png) + +### Session-Cookie 认证步骤解析 + +1. **客户端:** 向服务器发送登录信息用户名 / 密码来请求登录校验。 + +2. **服务器:** 验证登录的信息,验证通过后自动创建 Session(将 Session 保存在内存中,也可以保存在 Redis 中),然后给这个 Session 生成一个唯一的标识字符串会话身份凭证 session_id(通常称为 sid),并在响应头 Set-Cookie 中设置这个唯一标识符。 + + > 注:可以使用签名对 sid 进行加密处理,服务端会根据对应的 secret 密钥进行解密 (非必须步骤) + +3. **客户端:** 收到服务器的响应后会解析响应头,并自动将 sid 保存在本地 Cookie 中,浏览器在下次 HTTP 请求时请求头会自动附带上该域名下的 Cookie 信息。 + +4. **服务器:** 接收客户端请求时会去解析请求头 Cookie 中的 sid,然后根据这个 sid 去找服务端保存的该客户端的 sid,然后判断该请求是否合法。 + +### Session-Cookie 的优点 + +- Cookie 简单易用。 + +- Session 数据存储在服务端,相较于 JWT 方便进行管理,也就是当用户登录和主动注销,只需要添加删除对应的 Session 就可以了,方便管理。 + +- 只需要后端操作即可,前端可以无感等进行操作。 + +### Session-Cookie 的缺点 + +- 依赖 Cookie,一旦用户在浏览器端禁用 Cookie,那么就 GG 思密达了。 + +- 非常不安全,Cookie 将数据暴露在浏览器中,增加了数据被盗的风险(容易被 CSRF 等攻击)。 + +- Session 存储在服务端,增大了服务端的开销,用户量大的时候会大大降低服务器性能。 + +- 对移动端的支持性不友好。 + +### 使用场景 + +- 一般中大型的网站都适用(除了 APP 移动端)。 + +- 由于一般的 Session 需集中存储在内存服务器上(如 Redis),这样就会增加服务器的预算,所以预算不够请谨慎选择。 diff --git a/wiki/safe/系统权限/鉴权解决方案/Token 鉴权.md b/wiki/safe/系统权限/鉴权解决方案/Token 鉴权.md new file mode 100644 index 00000000..af223943 --- /dev/null +++ b/wiki/safe/系统权限/鉴权解决方案/Token 鉴权.md @@ -0,0 +1,85 @@ +--- +title: Token 鉴权 +description: Token 鉴权 +keywords: +- Token +- 鉴权 +tags: +- 权限 +sidebar_position: 3 +author: 7Wate +date: 2022-08-31 +--- +## Token 鉴权 + +现在我们已经得知,Session-Cookie 的一些缺点,以及 Session 的维护给服务端造成很大困扰,我们必须找地方存放它,又要考虑分布式的问题,甚至要单独为了它启用一套 Redis 集群。那有没有更好的办法? + +于是 Token 就应运而生了 + +### Token(令牌) + +Token 是一个令牌,客户端访问服务器时,验证通过后服务端会为其签发一张令牌,之后,客户端就可以携带令牌访问服务器,服务端只需要验证令牌的有效性即可。一句话概括:**访问资源接口(API)时所需要的资源凭证** + +#### Token 的组成 + +一般 Token 的组成由 **uid** (用户唯一的身份标识)+ **time**(当前时间的时间戳) + **sign** (签名,Token 的前几位以哈希算法压缩成的一定长度的十六进制字符串) + +#### Token 的认证流程图 + +![Token 的认证流程图](https://static.7wate.com/img/2022/08/30/40b2dbfe8f84a.png) + +#### Token 认证步骤解析 + +1. **客户端:** 输入用户名和密码请求登录校验。 +2. **服务器:** 收到请求验证用户名与密码;验证成功后,服务端会签发一个 Token,并把这个 Token 发送给客户端。 +3. **客户端:** 收到 Token 以后需要把它存储起来,Web 端一般会放在 localStorage 或 Cookie 中,移动端原生 APP 一般存储在本地缓存中。 +4. **客户端:** 再次向服务端请求 API 资源的时候,将 Token 通过 HTTP 请求头 Authorization 字段或者其它方式发送给服务端。 +5. **服务器:** 收到请求,然后去验证客户端请求里面带着的 Token ,如果验证成功,就向客户端返回请求的数据,否则拒绝返还(401)。 + +#### Token 的优点 + +- **服务端无状态化、可扩展性好:** Token 机制在服务端不需要存储会话(Session)信息,因为 Token 自身包含了其所标识用户的相关信息,这有利于在多个服务间共享用户状态。 +- **支持 APP 移动端设备。** +- **安全性好:** 有效避免 CSRF 攻击(因为不需要 Cookie)。 +- **支持跨程序调用:** 因为 Cookie 是不允许跨域访问的,而 Token 则不存在这个问题。 + +#### Token 的缺点 + +- **配合:** 需要前后端配合处理。 +- **占带宽:** 正常情况下比 sid 更大,消耗更多流量,挤占更多宽带。 +- **性能问题:** 虽说验证 Token 时不用再去访问数据库或远程服务进行权限校验,但是需要对 Token 加解密等操作,所以会更耗性能。 +- **有效期短:** 为了避免 Token 被盗用,一般 Token 的有效期会设置的较短,所以就有了 Refresh Token。 + +### Refresh Token(刷新 Token) + +业务接口用来鉴权的 Token,我们称之为 Access Token。为了安全,我们的 Access Token 有效期一般设置较短,以避免被盗用。但过短的有效期会造成 Access Token 经常过期,过期后怎么办呢? + +一种办法是**刷新 Access Token**,让用户重新登录获取新 Token,会很麻烦。另一种办法是再来一个 Token,一个专门生成 Access Token 的 Token,我们称为 **Refresh Token**。 + +- **Access Token:** 用来访问业务接口,由于有效期足够短,盗用风险小,也可以使请求方式更宽松灵活; +- **Refresh Token:** 用来获取 Access Token,有效期可以长一些,通过独立服务和严格的请求方式增加安全性;由于不常验证,也可以如前面的 Session 一样处理; + +#### Refresh Token 的认证流程图 + +![Refresh Token 的认证流程图](https://static.7wate.com/img/2022/08/30/0f634bdff18ca.png) + +#### Refresh Token 认证步骤解析 + +1. **客户端:** 输入用户名和密码请求登录校验。 +2. **服务端:** 收到请求,验证用户名与密码;验证成功后,服务端会签发一个 Access Token 和 Refresh Token 并返回给客户端; +3. **客户端:** 把 Access Token 和 Refresh Token 存储在本地; +4. **客户端:** 请求数据时,携带 Access Token 传输给服务端; +5. **服务端**: + - 验证 Access Token 有效:正常返回数据 + - 验证 Access Token 过期:拒绝请求 +6. **客户端** ( Access Token 已过期) **:** 则重新传输 Refresh Token 给服务端; +7. **服务端** ( Access Token 已过期) **:** 验证 Refresh Token ,验证成功后返回新的 Access Token 给客户端; +8. **客户端:** 重新携带新的 Access Token 请求接口; + +### Token 和 Session-Cookie 的区别 + +Session-Cookie 和 Token 有很多类似的地方,但是 Token 更像是 Session-Cookie 的升级改良版。 + +- **存储地不同:** Session 一般是存储在服务端;Token 是无状态的,一般由前端存储。 +- **安全性不同:** Session 和 Token 并不矛盾,作为身份认证 Token 安全性比 Session 好,因为每一个请求都有签名还能防止监听以及重放攻击。 +- **支持性不同:** Session-Cookie 认证需要靠浏览器的 Cookie 机制实现,如果遇到原生 NativeAPP 时这种机制就不起作用了,或是浏览器的 Cookie 存储功能被禁用,也是无法使用该认证机制实现鉴权的;而 Token 验证机制丰富了客户端类型。 diff --git a/wiki/safe/系统权限/鉴权解决方案/_category_.json b/wiki/safe/系统权限/鉴权解决方案/_category_.json new file mode 100644 index 00000000..948d013f --- /dev/null +++ b/wiki/safe/系统权限/鉴权解决方案/_category_.json @@ -0,0 +1,8 @@ +{ + "label": "鉴权解决方案", + "position": 3, + "link": { + "type": "generated-index", + "title": "鉴权解决方案" + } +} \ No newline at end of file diff --git a/wiki/safe/系统权限/鉴权解决方案/一键登录(适用于原生APP).md b/wiki/safe/系统权限/鉴权解决方案/一键登录(适用于原生APP).md new file mode 100644 index 00000000..dab02551 --- /dev/null +++ b/wiki/safe/系统权限/鉴权解决方案/一键登录(适用于原生APP).md @@ -0,0 +1,57 @@ +--- +title: 一键登录 +description: 一键登录 +keywords: +- 一键登录 +- APP +tags: +- 权限 +sidebar_position: 10 +author: 7Wate +date: 2022-08-31 +--- +## 一键登录(适用于原生APP) + +### 账号密码登录 + +大家都知道,最传统的登录方式就是使用**账号加密码登录**,简单粗暴,一般也不会出现什么问题;但这种方式的缺点如下: + +1. 但这种方式要求用户要记住自己的账号和密码,也就是有一个记忆成本。用户为了降低记忆成本,很可能会在不同平台使用同一套账号密码。从安全角度考虑,一旦某个平台的账号密码泄露了,会连累到该用户使用的其他平台。 +2. 另外,由于账号和个人身份无关,意味着同一个用户可以注册多个不同的账号,也就是可能会有恶意注册的情况发生。 + +**最后直到手机卡的强制实名制才得以解决!** + +### 手机号验证码登录 + +随着无线互联的发展以及手机卡实名制的推广,手机号俨然已成为特别的身份证明,与账号密码相比,手机号可以更好地验证用户的身份,防止恶意注册。 + +但是手机号注册还是需要一系列繁琐的操作:输入手机号、等待短信验证码、输入验证码、点击登录。整个流程少说二十秒,而且如果收不到短信,也就登录不了,问题有可能导致潜在的用户流失。 + +从安全角度考虑,还存在验证码泄漏的风险。如果有人知道了你的手机号,并且窃取到了验证码,那他也能登录你的账号了。 + +**所以就有了一键登录操作!** + +### 一键登录的定义 + +我们想一下,为什么我们需要验证码?验证码的作用就是确定这个手机号是你的,那除了使用短信,是否还有别的方式对手机号进行认证?于是,就有了咱们的主角**一键登录**。 + +短信验证码的作用:证明当前操作页面的用户与输入手机号的用户为相同的人,那么实际上只要我们能够获取到当前手机使用的手机卡号,直接使用这个号码进行登录,不需要额外的操作,这就是一键登录。 + +一键登录能不能做,取决于运营商是否开放相关服务;随着运营商开放了相关的服务,我们现在已经能够接入运营商提供的 SDK 并付费使用相关的服务。 + +### 一键登录流程图 + +![一键登录流程图](https://static.7wate.com/img/2022/08/30/855d4c809d739.png) + +### 一键登录步骤详解 + +1. **SDK 初始化:** 调用 SDK 方法,传入平台配置的 AppKey 和 AppSecret +2. **唤起授权页:** 调用 SDK 唤起授权接口,SDK 会先向运营商发起获取手机号掩码的请求,请求成功后跳到授权页。授权页会显示手机号掩码以及运营商协议给用户确认。 +3. **同意授权并登录:** 用户同意相关协议,点击授权页面的登录按钮,SDK 会请求本次取号的 Token,请求成功后将 Token 返回给客户端 +4. **取号:** 将获取到的 Token 发送到自己的服务器,由服务端携带 Token 调用运营商一键登录的接口,调用成功就返回手机号码。服务端用手机号进行登录或注册操作,返回操作结果给客户端,完成一键登录。 + +**三大运营商开放平台:**[移动 - 互联网能力开放平台](http://dev.10086.cn/)、[电信 - 天翼账号开放平台](https://id.dlife.cn/)、[联通 - WO+ 开放平台](https://onlinebusiness.10010.com/?chnl=none)。 + +由于国内三大运营商各自有独立的 SDK,所以会导致兼容方面的工作会特别繁琐。如果要采用一键登录的方案,不妨采用第三方提供了号码认证服务,下列几家供应商都拥有手机号码认证能力:[阿里 - 号码认证服务](https://help.aliyun.com/product/75010.html)、[创蓝 - 闪验](http://shanyan.253.com/)、[极光 - 极光认证](https://www.jiguang.cn/identify)、[mob - 秒验](https://www.mob.com/mobService/secverify) + +在认证过程中,需要用户打开蜂窝网络,如果手机设备没有插入 SIM 卡、或者关闭蜂窝网络的情况下,是无法完成认证的。所以就算接入一键登录,还是要兼容传统的登录方式,允许用户在失败的情况下,仍能正常完成登录流程。 \ No newline at end of file diff --git a/wiki/safe/系统权限/鉴权解决方案/单点登录(Single Sign On).md b/wiki/safe/系统权限/鉴权解决方案/单点登录(Single Sign On).md new file mode 100644 index 00000000..53663030 --- /dev/null +++ b/wiki/safe/系统权限/鉴权解决方案/单点登录(Single Sign On).md @@ -0,0 +1,70 @@ +--- +title: SSO 单点登录 +description: SSO 单点登录 +keywords: +- 单点登录 +- SSO +- Single Sign On +tags: +- 权限 +sidebar_position: 5 +author: 7Wate +date: 2022-08-31 +--- + +## 单点登录(Single Sign On) + +现在随着企业的发展,一个大型系统里可能包含 n 多子系统,用户在操作不同的系统时,需要多次登录,很麻烦,那么**单点登录(SSO)**就可以很好的解决这个问题的,在**多个应用系统中,只需要登录一次,就可以访问其他相互信任的应用系统**。 + +例如登录天猫,淘宝也会自动登录;登录百度贴吧,百度网盘也会自动登录。 + +### 同域下的 SSO(主域名相同) + +当百度网站存在两个相同主域名下的贴吧子系统 tieba.baidu.com 和网盘子系统 pan.baidu.com 时,以下为它们实现 SSO 的步骤: + +1. **客户端:** 用户访问某个子系统时(例如 tieba.baidu.com),如果没有登录,则跳转至 SSO 认证中心提供的登录页面进行登录。 +2. **服务端:** 登录认证后,服务端把登录用户的信息存储于 Session 中,并且附加在响应头的 Set-Cookie 字段中,设置 Cookie 的 Domain 为 .baidu.com ; +3. 客户端:再次发送请求时,携带主域名 Domain 下的 Cookie 给服务器,此时服务端就可以通过该 Cookie 来验证登录状态了; + +### 跨域下的 SSO(主域名不同) + +在我们常见的购物网站天猫(tmall.com)和 淘宝(taobao.com)中,我们只需要登录其中某一个系统,另外一个系统打开后就会默认登录,那么这是怎么做的呢? + +那么就有了 **CAS(Central Authentication Service)中央授权服务**,那么我们先主要说下 CAS 的流程。 + +#### 单点登录下的 CAS 认证流程图 + +![单点登录下的 CAS 认证流程图](https://static.7wate.com/img/2022/08/30/227748c758a02.png) + +#### 单点登录下的 CAS 认证步骤详解 + +1. **客户端:** 访问系统 A。 +2. **系统 A:** 发现用户未登录,重定向至 CAS 认证服务(sso.com),同时 URL 地址参数携带登录成功后回跳到系统 A 的页面链接 `sso.com/login?redir…` +3. **CAS 认证服务:** 发现请求 Cookie 中没有携带登录的票据凭证(TGC),所以 CAS 认证服务判定用户处于**未登录状态**,重定向用户页面至 CAS 的登录界面,用户在 CAS 的登录页面上进行登录操作。 +4. **客户端:** 输入用户名密码进行 CAS 系统认证; +5. **CAS 认证服务:** 校验用户信息,并且生成 TGC 放入自己的 Session 中,同时以 Set-Cookie 形式写入 Domain 为 sso.com 的域下 ;同时生成一个授权令牌 ST (Service Ticket),然后重定向至系统 A 的地址,重定向的地址中包含生成的 ST,重定向地址 `www.taobao.com?token=ST-345678` +6. **系统 A:** 拿着 ST 向 CAS 认证服务发送请求,CAS 认证服务验证票据 (ST) 的有效性。验证成功后,系统 A 知道用户已经在 CAS 登录了(其中的 ST 可以保存到 Cookie 或者本地中),系统 A 服务器使用该票据 (ST) 创建与用户的会话,称为局部会话,返回受保护资源。 + +***到这里客户端就可以跟系统 A 愉快的交往啦 ~*** + +1. **客户端:** 开始访问系统 B。 +2. **系统 B:** 发现用户未登录,重定向至 SSO 认证服务,并将自己的地址作为参数传递,并附上在 sso.com 域下的 cookie 值是第五步生成的 TGC。 +3. **CAS 认证服务:** CAS 认证服务中心发现用户已登录,跳转回系统 B 的地址,并附上票据 (ST) ; +4. **系统 B:** 拿到票据 (ST),去 CAS 认证服务验证票据 (ST) 的有效性。验证成功后,客户端也可以跟系统 B 交往了 ~ + +#### 单点登录下需要注意的地方 + +如图中流程所示,我们发现 CAS 认证服务在签发的授权令牌 ST 后,直接重定向,这样其实是比较容易容易被窃取,那么我们需要在系统 A 或者系统 B 在向 CAS 验证成功 (如图中的第 14 步和第 11 步) 后,再生成另一个新的验证 Token 返回给客户端保存。 + +#### CAS 常用接口 + +- **login**:登录接口,用于登录到中央授权服务 +- **logout**:登出接口,用于从中央授权服务中登出 +- **validate**:用于验证用户是否登录中央授权服务 +- **serviceValidate**:用于让各个 Service 验证用户是否登录中央授权服务 + +#### CAS 生成的票据 + +- **TGT(Ticket Grangting Ticket)** :TGT 是 CAS 为用户签发的登录票据,拥有了 TGT,用户就可以证明自己在 CAS 成功登录过。 +- **TGC:Ticket Granting Cookie:** CAS Server 生成TGT放入自己的 Session 中,而 TGC 就是这个 Session 的唯一标识(SessionId),以 Cookie 形式放到浏览器端,是 CAS Server 用来明确用户身份的凭证。 +- **ST(Service Ticket)** :ST 是 CAS 为用户签发的访问某个 Service 的票据。 diff --git a/wiki/safe/系统权限/鉴权解决方案/唯一登录.md b/wiki/safe/系统权限/鉴权解决方案/唯一登录.md new file mode 100644 index 00000000..c4bc7fe5 --- /dev/null +++ b/wiki/safe/系统权限/鉴权解决方案/唯一登录.md @@ -0,0 +1,38 @@ +--- +title: 唯一登录 +description: 唯一登录 +keywords: +- 唯一登录 +tags: +- 权限 +sidebar_position: 8 +author: 7Wate +date: 2022-08-31 +--- + +## 唯一登录 + +### 唯一登录定义 + +唯一登录是指**禁止多人同时登录同一账号,后者的登录行为,会导致前者掉线。** + +通俗点讲就是:A 账号在 A 电脑上登录后,A 账号此时又用 B 电脑再次登录,则 A 电脑请求页面时,提示“重新登录”的信息,并跳转到登录页面 + +### 唯一登录流程图 + +![唯一登录流程图](https://static.7wate.com/img/2022/08/30/f71a772c45d73.png) + +### 唯一登录步骤详解 + +#### 用户 - 客户端 A 操作 + +1. 输入账号请求登录接口。 +2. 后端生成对应 Token 并且返回给客户端 A,并且在服务端保存一个登录状态。 +3. 客户端 A 保存 Token,并且每次请求都在 header 头中携带对应的 Token。 + +#### 用户 - 客户端 B 操作 + +1. 输入账号请求登录接口。 +2. …… + +用户在客户端 B 上开始登录操作时,我们会发现,步骤和在客户端A上面的操作几乎是一致的。只是后端在生成新的 Token 时,要**先验证登录状态**,然后再生成对应新的 Token; \ No newline at end of file diff --git a/wiki/safe/系统权限/鉴权解决方案/扫码登录.md b/wiki/safe/系统权限/鉴权解决方案/扫码登录.md new file mode 100644 index 00000000..1c3dede3 --- /dev/null +++ b/wiki/safe/系统权限/鉴权解决方案/扫码登录.md @@ -0,0 +1,48 @@ +--- +title: 扫码登录 +description: 扫码登录 +keywords: +- 扫码登录 +- 二维码 +tags: +- 权限 +sidebar_position: 9 +author: 7Wate +date: 2022-08-31 +--- +## 扫码登录 + +### 扫码登录定义 + +扫码登录通常见于移动端 APP 中,很多 PC 端的网站都提供了扫码登录的功能,无需在网页上输入任何账号和密码,只需要让移动端 APP(如微信、淘宝、QQ等等)中已登录用户主动扫描二维码 ,再确认登录,以使 PC 端的同款应用得以快速登录的方式就是扫码登录 。 + +### 二维码定义 + +二维码又称二维条码,常见的二维码为 QR Code,QR 全称 Quick Response,是一个近几年来移动设备上超流行的一种编码方式,它比传统的 Bar Code 条形码能存更多的信息,也能表示更多的数据类型。 + +### 扫码登录的认证流程图 + +![扫码登录的认证流程图](https://static.7wate.com/img/2022/08/30/3a298ee5cc11d.png) + +### 扫码登录的步骤详解 + +#### 1. 待扫码阶段 + +1. **桌面端:**打开某个网站(如taobao.com)或者某个 APP 的扫码登录入口;就会携带 PC 端的设备信息向服务端发送一个获取二维码的请求。 +2. **服务端:**服务器收到请求后,随机生成一个 UUID 作为二维码 ID,并将 UUID 与桌面端的设备信息关联起来存储在 Redis 服务器中,然后返回给 PC 端;同时设置一个过期时间,在过期后,用户登录二维码需要进行刷新重新获取。 +3. **桌面端:**收到二维码 ID 之后,将二维码 ID 以二维码的形式展示,等待移动端扫码。并且此时的桌面端开始轮询查询二维码状态,直到登录成功。 +4. 如果移动端未扫描,那么一段时间后二维码会自动失效。 + +#### 2. 已扫码待确认阶段 + +1. **移动端:**打开手机端对应已登录的 APP (微信或淘宝等),开始扫描识别桌面端展示的二维码;移动端扫描二维码后,会自动获取到二维码 ID,并将移动端登录的信息凭证(Token)和二维码 ID 作为参数发送给服务端,此时手机必须是已登录(使用扫描登录的前提是移动端的应用为已登录状态,这样才可以共享登录态)。 + +2. **服务端:**收到手机端发来的请求后,会将 Token 与二维码 ID 关联,为什么需要关联呢?因为,当我们在使用微信时,移动端退出时,PC 端也应该随之退出登录,这个关联就起到这个作用。然后会生成一个临时 Token,这个 Token 会返回给移动端,一次性 Token 用作确认时的凭证。 + +#### 3. 已确认阶段 + +1. **移动端:**收到确认信息后,点击确认按钮,移动端携带上一步中获取的临时 Token 发送给服务端校验; + +2. **服务端:**服务端校验完成后,会更新二维码状态,并且给 PC 端生成一个正式的 Token,后续 PC 端就是持有这个 Token 访问服务端。 + +3. **桌面端:**轮询到二维码状态为已登录状态,并且会获取到了生成的 Token,完成登录,后续访问都基于 Token 完成。 diff --git a/wiki/safe/系统权限/鉴权解决方案/联合登录和信任登录.md b/wiki/safe/系统权限/鉴权解决方案/联合登录和信任登录.md new file mode 100644 index 00000000..65695f7a --- /dev/null +++ b/wiki/safe/系统权限/鉴权解决方案/联合登录和信任登录.md @@ -0,0 +1,31 @@ +--- +title: 联合登录和信任登录 +description: 联合登录和信任登录 +keywords: +- 联合登录 +- 信任登录 +tags: +- 权限 +sidebar_position: 7 +author: 7Wate +date: 2022-08-31 +--- +## 联合登录和信任登录 + +### 联合登录定义 + +联合登录指同时包含多种凭证校验的登录服务,同时,也可以理解为使用第三方凭证进行校验的登录服务。 + +通俗点讲:**对于两个网站 A 和 B,在登录 A 网站的时候用 B 网站的帐号密码,就是联合登录,或者登录 B 网站的时候使用 A 网站的帐号密码,也是联合登录。** + +这样的概念其实与上面所讲的 OAuth2.0 的用户名密码式模式认证方式类似。最经典的莫过于 APP 内嵌 H5 的使用场景,当用户从 APP 进入内嵌的 H5 时,我们希望 APP 内已登录的用户能够访问到 H5 内受限的资源,而未登录的用户则需要登录后访问。 + +这里思路主要有两种,一种是原生跳转内嵌 H5 页面时,将登录态 Token 附加在 URL 参数上,另一种则是内嵌 H5 主动通过与原生客户端制定的协议获取应用内的登录状态。 + +### 信任登录定义 + +信任登录是指所有不需要用户主动参与的登录,例如建立在私有设备与用户之间的绑定关系,凭证就是私有设备的信息,此时不需要用户再提供额外的凭证。信任登录又指用第三方比较成熟的用户库来校验凭证,并登录当前访问的网站。 + +通俗点讲: **在 A 网站有登录状态的时候,可以直接跳转到 B 网站而不用登录,就是信任登录。** + +目前比较常见的第三方信任登录帐号如:QQ 号淘宝帐号、支付宝帐号、微博帐号等。我们不难发现 OAtuth 2.0 其实就是信任登录的缩影,因为正是有了 OAuth,我们的信任登录才得以实现。