ip-filter.md 5.2 KB
Newer Older
雪洛's avatar
雪洛 已提交
1
> 新增于HBuilderX 3.5.4
雪洛's avatar
雪洛 已提交
2 3 4 5 6

IP防刷功能旨在防范短时间内大量相同ip请求导致云函数或数据库无法及时响应。此功能包含两个子功能:IP黑名单、IP访问频率控制。

## 启用IP防刷功能

雪洛's avatar
雪洛 已提交
7 8
1. 服务空间内开通了redis
2. 在uniCloud web控制台开启相关功能:[uniCloud web控制台](https://unicloud.dcloud.net.cn/)
雪洛's avatar
雪洛 已提交
9 10 11 12

**注意**

- 此功能对clientDB生效
雪洛's avatar
雪洛 已提交
13
- 启用了redis扩展、jql扩展(jql扩展依赖了redis扩展)的云函数或云对象才会有防刷功能。
雪洛's avatar
雪洛 已提交
14
- 仅在客户端callFunction调用云函数时才会启用IP防刷功能。url化、定时触发、云函数调用云函数均不触发此功能
雪洛's avatar
雪洛 已提交
15 16 17 18 19

## IP黑名单@ip-black-list

IP黑名单是用来完全阻止设定的IP或IP网段(cidr规范)访问云函数或clientDB的功能。

雪洛's avatar
雪洛 已提交
20
![black list](https://vkceyugu.cdn.bspapp.com/VKCEYUGU-f184e7c3-1912-41b2-b81f-435d1b37c7b4/7bf5e358-e627-4b3a-bafb-2b18d43c4d4b.jpg)
雪洛's avatar
雪洛 已提交
21 22 23 24

被封禁IP访问云函数及clientDB时会收到错误响应,错误码为:`ACCESS_DENIED`,错误信息为:`Access denied`

```js
雪洛's avatar
雪洛 已提交
25 26 27 28 29 30 31 32 33 34 35 36
// 云函数
const res = await uniCloud.callFunction({
  name: 'test',
  data: {}
})
// res.result = {
//   errCode: 'ACCESS_DENIED',
//   errMsg: 'Access denied'
// }

// 对于云对象而言,上述返回结果符合响应体规范因为会转化为错误抛出
const obj = uniCloud.importObject('obj')
雪洛's avatar
雪洛 已提交
37
try {
雪洛's avatar
雪洛 已提交
38
  const res = await obj.test()
雪洛's avatar
雪洛 已提交
39
} catch (e) {
雪洛's avatar
雪洛 已提交
40 41
  // e.errCode = 'ACCESS_DENIED'
  // e.errMsg = 'Access denied'
雪洛's avatar
雪洛 已提交
42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68
}
```

### IP网段规则

通常书写IPv4地址时会将IPv4地址写成由点分割的四段数字,每段取值范围为0-255。IP网段则是由IP加掩码位数组成的字符串,用于表示一个IP区间。

`192.168.12.1/20`为例,要计算其表示的IP区间可以先将四段IP转为二进制(每段不足8位的往前补0)`11000000.10101000.00001100.00000001`,掩码位数20则表示经过此规则转化后的IP只要前20位和`192.168.12.1`转换后相同则此IP在`192.168.12.1/20`这个IP网段内。即IP区间为`11000000.10101000.00000000.00000000`(192.168.0.0) - `11000000.10101000.00001111.11111111`(192.168.15.255)

### 黑名单用到的Redis key

开发者配置的黑名单会以Set类型存储在redis内,其key为:`unicloud:ip-black-list:set`

### 注意事项

- 切换开关状态会更新所有依赖或间接依赖redis扩展的云函数及clientDB
- 一个区域内的多个用户可能拥有同一IP

## IP访问频率控制@ip-freq

IP访问频率控制用于限制单个IP访问云函数的频率。如图所示,开发者可以配置`${duration}秒内请求超过${limit}次,则将会临时封禁${blockTime}秒`

就客户端体验来说这个配置表示,**任意连续**duration秒内访问均不可超过limit次,否则将会临时封禁blockTime秒。对于有相关开发经验的开发者来说应该很容易看出这就是一个漏桶算法的实现。

- blockTime配置为0时超出限制也不会进行封禁,只是拒绝请求。
- duration或limit配置为0时将不再限制访问频率,但是已被临时封禁的用户依然需要等到解封后才可以访问

雪洛's avatar
雪洛 已提交
69
![frequency limit](https://vkceyugu.cdn.bspapp.com/VKCEYUGU-f184e7c3-1912-41b2-b81f-435d1b37c7b4/76130f29-7c64-4406-af69-a3759e264726.jpg)
雪洛's avatar
雪洛 已提交
70 71 72 73

访问频率过高的用户及由于访问频率过高被临时封禁的用户访问云函数及clientDB时会收到错误响应,错误码为:`OPERATION_TOO_FREQUENT`,错误信息为:`Operation is too frequent, please try again later`

```js
雪洛's avatar
雪洛 已提交
74 75 76 77 78 79 80 81 82 83 84 85
// 云函数
const res = await uniCloud.callFunction({
  name: 'test',
  data: {}
})
// res.result = {
//   errCode: 'OPERATION_TOO_FREQUENT',
//   errMsg: 'Operation is too frequent, please try again later'
// }

// 对于云对象而言,上述返回结果符合响应体规范因为会转化为错误抛出
const obj = uniCloud.importObject('obj')
雪洛's avatar
雪洛 已提交
86
try {
雪洛's avatar
雪洛 已提交
87
  const res = await obj.test()
雪洛's avatar
雪洛 已提交
88
} catch (e) {
雪洛's avatar
雪洛 已提交
89 90
  // e.errCode = 'OPERATION_TOO_FREQUENT'
  // e.errMsg = 'Operation is too frequent, please try again later'
雪洛's avatar
雪洛 已提交
91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131
}
```

### IP访问频率控制用到的Redis key

**访问频率控制配置**

开发者配置的duration、limit、blockTime三个参数以hash类型存储在redis内,key为:`unicloud:ip-freq-config:hash`

结构如下:

```js
{
	"duration": 10, // 单位秒
	"limit": 10, // 10(duration)秒内允许访问10次
	"blockTime": 1800 // 超限后封禁1800秒
}
```

**IP频率控制信息**

IP频率控制信息的以hash类型存储在redis内,key为:`unicloud:ip-info:${ip}:hash`其中${ip}表示客户端的ip

结构示例如下:

```js
{
	"bucket": 20, // 剩余访问次数,最大为配置的limit,最小为 0,以上面的访问频率控制配置为例
	"lastTime": 1656399171851 // 上次剩余访问次数变动的时间
}
```

**临时封禁信息**

临时封禁信息以string类型存储在redis内,key为:`unicloud:ip-blocked:${ip}:string`其中${ip}表示客户端的ip

其值为临时封禁开始的时间戳

### 注意事项

- 切换开关状态会更新所有依赖或间接依赖redis扩展的云函数及clientDB
雪洛's avatar
雪洛 已提交
132 133
- 一个区域内的多个用户可能拥有同一IP
- 本地调试期间如果开启或关闭了IP防刷功能,应停止所有客户端等待5秒重新运行才可生效