系统权限:鉴权解决方案
This commit is contained in:
parent
562dbc04bd
commit
c00249e1d3
@ -316,7 +316,7 @@ const config = {
|
|||||||
theme: lightCodeTheme,
|
theme: lightCodeTheme,
|
||||||
darkTheme: darkCodeTheme,
|
darkTheme: darkCodeTheme,
|
||||||
defaultLanguage: "markdown",
|
defaultLanguage: "markdown",
|
||||||
additionalLanguages: ["java", "git","nginx"],
|
additionalLanguages: ["java", "git","nginx","http"],
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
|
@ -5,8 +5,7 @@ keywords:
|
|||||||
- 关键字
|
- 关键字
|
||||||
tags:
|
tags:
|
||||||
- 标签
|
- 标签
|
||||||
|
sidebar_position: 1
|
||||||
author: 7Wate
|
author: 7Wate
|
||||||
date: <% tp.date.now("YYYY-MM-DD") %>
|
date: <% tp.date.now("YYYY-MM-DD") %>
|
||||||
---
|
---
|
||||||
|
|
||||||
一篇文档 - 快速模板
|
|
8
wiki/safe/系统权限/权限设计方案/_category_.json
Normal file
8
wiki/safe/系统权限/权限设计方案/_category_.json
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"label": "权限设计方案",
|
||||||
|
"position": 2,
|
||||||
|
"link": {
|
||||||
|
"type": "generated-index",
|
||||||
|
"title": "权限设计方案"
|
||||||
|
}
|
||||||
|
}
|
@ -79,7 +79,7 @@ RBAC三要素:
|
|||||||
|
|
||||||
**优点**:便于角色划分,更灵活的授权管理;最小颗粒度授权;
|
**优点**:便于角色划分,更灵活的授权管理;最小颗粒度授权;
|
||||||
|
|
||||||
![基于角色的权限控制](https://static.7wate.com/img/2022/08/08/e11745fdd5e0f.png)
|
![RBAC](https://static.7wate.com/img/2022/08/30/2fb0d9ad61795.png)
|
||||||
|
|
||||||
## RBAC的深度拓展
|
## RBAC的深度拓展
|
||||||
|
|
||||||
@ -95,13 +95,13 @@ RBAC模型可以分为:**RBAC0**、**RBAC1**、**RBAC2**、**RBAC3** 四个阶
|
|||||||
|
|
||||||
**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 模型做权限系统,我可能需要为经理、主管、专员分别创建一个角色(角色之间权限无继承性),极有可能出现一个问题,由于权限配置错误,主管拥有经理都没有权限。
|
||||||
|
|
||||||
@ -111,7 +111,7 @@ RBAC模型可以分为:**RBAC0**、**RBAC1**、**RBAC2**、**RBAC3** 四个阶
|
|||||||
|
|
||||||
基于 **RBAC0** 模型,对角色增加了更多约束条件。
|
基于 **RBAC0** 模型,对角色增加了更多约束条件。
|
||||||
|
|
||||||
![RBAC2](https://static.7wate.com/img/2022/08/08/83e2b3f4e2f85.png)
|
![RBAC2](https://static.7wate.com/img/2022/08/30/adc688e2b7f77.png)
|
||||||
|
|
||||||
如**角色互斥**,比较经典的案例是财务系统中出纳不得兼管稽核,那么在赋予财务系统操作人员角色时,同一个操作员不能同时拥有出纳和稽核两个角色。
|
如**角色互斥**,比较经典的案例是财务系统中出纳不得兼管稽核,那么在赋予财务系统操作人员角色时,同一个操作员不能同时拥有出纳和稽核两个角色。
|
||||||
|
|
||||||
@ -139,7 +139,7 @@ RBAC 权限模型由三大部分构成,即**用户管理**、**角色管理**
|
|||||||
|
|
||||||
用户管理中的用户,是企业里每一位员工,他们本身就有自己的组织架构,我们可以直接使用企业部门架构或者业务线架构来作为线索,构建用户管理系统。
|
用户管理中的用户,是企业里每一位员工,他们本身就有自己的组织架构,我们可以直接使用企业部门架构或者业务线架构来作为线索,构建用户管理系统。
|
||||||
|
|
||||||
![用户管理](https://static.7wate.com/img/2022/08/08/71d1e4799cbf1.png)
|
![用户管理系统](https://static.7wate.com/img/2022/08/30/887a6f017f7e3.png)
|
||||||
|
|
||||||
**需要特殊注意**:实际业务中的组织架构可能与企业部门架构、业务线架构不同,需要考虑数据共享机制,一般的做法为授权某个人、某个角色组共享某个组织层级的某个对象组数据。
|
**需要特殊注意**:实际业务中的组织架构可能与企业部门架构、业务线架构不同,需要考虑数据共享机制,一般的做法为授权某个人、某个角色组共享某个组织层级的某个对象组数据。
|
||||||
|
|
||||||
@ -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. 页面/菜单权限
|
#### 1. 页面/菜单权限
|
||||||
|
|
||||||
@ -193,7 +193,7 @@ RBAC 权限模型由三大部分构成,即**用户管理**、**角色管理**
|
|||||||
|
|
||||||
#### 4. 数据权限如何管控
|
#### 4. 数据权限如何管控
|
||||||
|
|
||||||
数据权限可以分为行权限和列权限。行权限控制:看多少条数据。列权限控制:看一条数据的多少个字段
|
数据权限可以分为行权限和列权限。行权限控制:看多少条数据。列权限控制:看一条数据的多少个字段。
|
||||||
|
|
||||||
简单系统中可以通过组织架构来管控行权限,按照角色来配置列权限,但是遇到复杂情况,组织架构是承载不了复杂行权限管控,角色也更不能承载列的特殊化展示。
|
简单系统中可以通过组织架构来管控行权限,按照角色来配置列权限,但是遇到复杂情况,组织架构是承载不了复杂行权限管控,角色也更不能承载列的特殊化展示。
|
||||||
|
|
52
wiki/safe/系统权限/系统权限简明指南.md
Normal file
52
wiki/safe/系统权限/系统权限简明指南.md
Normal file
@ -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)
|
||||||
|
|
||||||
|
**认证**、**授权**、**鉴权**和**权限控制**,这四个环节是一个**前后依次发生**、**上下游**的关系;需要说明的是,这四个环节在有些时候会同时发生。 例如在下面的几个场景:
|
||||||
|
|
||||||
|
- **使用门禁卡开门:** 认证、授权、鉴权、权限控制四个环节一气呵成,在瞬间同时发生。
|
||||||
|
|
||||||
|
- **用户的网站登录:** 用户在使用用户名和密码进行登录时,认证和授权两个环节一同完成,而鉴权和权限控制则发生在后续的请求访问中,比如在选购物品或支付时。
|
74
wiki/safe/系统权限/鉴权解决方案/HTTP 基本鉴权.md
Normal file
74
wiki/safe/系统权限/鉴权解决方案/HTTP 基本鉴权.md
Normal file
@ -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 认证信息,除非标签页或浏览器关闭、或用户清除历史记录。
|
||||||
|
|
||||||
|
### 使用场景
|
||||||
|
|
||||||
|
内部网络,或者对安全要求不是很高的网络。
|
105
wiki/safe/系统权限/鉴权解决方案/JWT(JSON Web Token)鉴权.md
Normal file
105
wiki/safe/系统权限/鉴权解决方案/JWT(JSON Web Token)鉴权.md
Normal file
@ -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 <token>
|
||||||
|
```
|
||||||
|
|
||||||
|
### 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 签发了,在到期之前就会始终有效,除非服务器部署额外的逻辑。
|
220
wiki/safe/系统权限/鉴权解决方案/OAuth 鉴权.md
Normal file
220
wiki/safe/系统权限/鉴权解决方案/OAuth 鉴权.md
Normal file
@ -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)
|
106
wiki/safe/系统权限/鉴权解决方案/Session-Cookie 鉴权.md
Normal file
106
wiki/safe/系统权限/鉴权解决方案/Session-Cookie 鉴权.md
Normal file
@ -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),这样就会增加服务器的预算,所以预算不够请谨慎选择。
|
85
wiki/safe/系统权限/鉴权解决方案/Token 鉴权.md
Normal file
85
wiki/safe/系统权限/鉴权解决方案/Token 鉴权.md
Normal file
@ -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 验证机制丰富了客户端类型。
|
8
wiki/safe/系统权限/鉴权解决方案/_category_.json
Normal file
8
wiki/safe/系统权限/鉴权解决方案/_category_.json
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"label": "鉴权解决方案",
|
||||||
|
"position": 3,
|
||||||
|
"link": {
|
||||||
|
"type": "generated-index",
|
||||||
|
"title": "鉴权解决方案"
|
||||||
|
}
|
||||||
|
}
|
57
wiki/safe/系统权限/鉴权解决方案/一键登录(适用于原生APP).md
Normal file
57
wiki/safe/系统权限/鉴权解决方案/一键登录(适用于原生APP).md
Normal file
@ -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 卡、或者关闭蜂窝网络的情况下,是无法完成认证的。所以就算接入一键登录,还是要兼容传统的登录方式,允许用户在失败的情况下,仍能正常完成登录流程。
|
70
wiki/safe/系统权限/鉴权解决方案/单点登录(Single Sign On).md
Normal file
70
wiki/safe/系统权限/鉴权解决方案/单点登录(Single Sign On).md
Normal file
@ -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 的票据。
|
38
wiki/safe/系统权限/鉴权解决方案/唯一登录.md
Normal file
38
wiki/safe/系统权限/鉴权解决方案/唯一登录.md
Normal file
@ -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;
|
48
wiki/safe/系统权限/鉴权解决方案/扫码登录.md
Normal file
48
wiki/safe/系统权限/鉴权解决方案/扫码登录.md
Normal file
@ -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 完成。
|
31
wiki/safe/系统权限/鉴权解决方案/联合登录和信任登录.md
Normal file
31
wiki/safe/系统权限/鉴权解决方案/联合登录和信任登录.md
Normal file
@ -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,我们的信任登录才得以实现。
|
Loading…
Reference in New Issue
Block a user