# 存储安全规则

安全规则是在基础权限控制基础上，更高级、灵活、可扩展的一种权限控制方式，由**身份验证**、**授权**和**安全规则表达式**三部分构成。

云存储安全规则可用于确定哪些人对云存储桶中存储的文件拥有读取和写入权限，也可用于文件中包含的元数据校验。

:::tip 提示

- 你可以在微信云开发·云后台中对云存储进行安全规则权限的设置；
- 云后台和服务端始终有所有文件读写权限，安全规则的配置仅对客户端（小程序端、Web 等）发起的请求有效；
- 修改更新安全规则，权限生效需要 1- 3 分钟，请耐心等待；
- 发布之前，请务必评估你的规则，确保它们可以为你的应用提供所需的最高级别的安全性。如果发布应用时设置的是 public 规则，可能会导致你存储的数据遭到意外访问或未经授权的访问。

:::

## 基础权限控制与云存储安全规则

云存储提供基础的权限控制，默认为“所有用户可读，仅创建者可读写”，基础权限控制都可以通过安全规则权限控制得到。

### 所有用户可读，仅创建者及管理员可写

```js
{
  "read": true,
  "write": "resource.openid == auth.openid", // 登录方式为微信
  "write": "resource.openid == auth.uid" // 登录方式为非微信
}
```

#### 仅创建者及管理员可读写

```js
{
  "read": "resource.openid == auth.openid", //登录方式为微信
  "read": "resource.openid == auth.uid", // 登录方式为非微信
  "write": "resource.openid == auth.openid", //登录方式为微信
  "write": "resource.openid == auth.uid" // 登录方式为非微信
}
```

##### 所有用户可读，仅管理员可写

```js
{
  "read": true,
  "write": false
}
```

##### 仅管理员可读写

```js
{
  "read": false,
  "write": false
}
```

### 身份验证

云存储安全规则结合集成的用户身份验证可以实现身份校验能力，开发者可以根据用户身份信息进行精准的资源访问控制。

当 C 端用户登录后，安全规则中 `auth` 变量会变成一个包含该用户唯一 ID（`auth.uid`）和登录方式（`auth.loginType`）的对象。反之用户未登录，则`auth`的值为 null。通过 `auth` 规则可以实现对每个用户的数据访问控制。

经过身份认证的用户发起请求时，系统会使用用户唯一 id `uid` 及用户登录方式 `loginType` 填充 `auth` 变量。

通过 `auth` 变量，可以用以下常用方式来根据身份对文件访问进行控制：

- 公开：不判断 `auth` 值。
- 只对已登录用户公开：检查 `auth` 不为 `null`。
- 用户私有：检查 `auth.uid` 是否等于资源 `openid`。
- 仅对某种特殊的登录方式进行判断，限制匿名登录用户访问，检查 `auth.loginType` 不为 `ANONYMOUS`

### 授权

识别用户身份只是安全工作的一部分。在知道用户的身份后，开发者需要一种方法来控制该用户对云存储中的文件的访问权限。

云存储支持存储桶级别的授权规则，通过设置安全规则表达式可以对云存储空间内的所有文件的读写操作进行限制。

### 安全规则表达式

安全规则表达式通过 `json` 来描述，允许在满足条件时执行 `read` 及 `write` 操作，示例配置如下：

```js
{
  "read": boolean | condition expression string,
}
```

`json` 配置的 `key`，是用户的**操作类型**，`value` 是一个表达式。当表达式执行结果的值是 `true` 的时候，用户的操作允许执行；否则，用户的操作则不被允许。

| 操作类型 | 说明                     | 默认值 |
| :------- | :----------------------- | :----- |
| read     | 读取文件，例如：download | false  |
| write    | 上传/覆盖文件，删除文件  | false  |

规则验证所依据的上下文通过 `auth`、`resource` 对象获得，其提供可验证身份的上下文信息（`auth.uid`）和对象所有权（`resource.openid`）等信息。

```json
{
  "read": "auth.uid == resource.openid",
  "write": "auth != null"
}
```

### 示例

#### 公开

任何不考虑 `auth` 的规则均可被视为 `public` 规则，因为他不考虑用户的身份验证上下文，这些规则在呈现公开数据（静态资源内容）的场景下是很适用。

```json
{
  "read": "resource.openid != null"
}
```

##### 对登录的用户开放

在某些情况下，你可能希望限制只有登录用户在可以访问用户数据。例如，登录用户才可以查看论坛中的讨论。由于所有未登录用户的 `auth` 变量为 `null`，因此可以设置如下规则：

```json
{
  "read": "auth != null"
}
```

##### 用户私有

`auth` 最常见的使用场景在为个人用户资源提供精细的访问控制，例如上传私人照片等。云存储文件中包含了文件所有者信息(用户唯一 id)，在规则中可以如此限制：

```json
{
  "read": "auth.uid == resource.openid",
  "write": "auth.uid == resource.openid"
}
```

##### 实际案例

在一个相册应用中，希望所有登录用户都可以上传，浏览广场图片，不允许未登录用户访问，单可以使用匿名登录访问，匿名身份下只可以浏览，不可上传，则可以对存储设置如下规则。

```json
{
  "read": "auth != null",
  "write": "auth.loginType != 'ANONYMOUS' && auth.openid == resource.openid"
}
```
