# 私有图片 (/zh/docs/guides/private)

把图片设为私有，只有带有效签名的链接能访问：怎么设置、怎么生成有时效的签名链接，以及它与缓存、302、防盗链的关系和能防什么、不能防什么。

## 什么时候用 [#什么时候用]

默认情况下，图片链接是公开的：知道链接就能访问。有些图片只想给特定的人看一阵子，比如还没发布的文章配图、发给同事的截图。把它们设为私有图片：

- 私有图片的公开链接（`/i/<id>`）打不开，返回 404。
- 只有带有效签名的链接能访问。签名链接有时效，到期即失效。
- 私有图片一律经本服务输出，不走渠道直链，也不会被 CDN 缓存。

## 设为私有 [#设为私有]

三种方式：

- **上传时指定**：表单字段或 JSON 字段 `private` 取 `true`，见[上传](./upload.mdx#私有图片)。管理后台的「上传图片」对话框里有「私有」开关。
- **之后修改**：图片详情里的「私有图」开关，或接口 `PATCH /api/admin/images/{id}` 带 `private`。图片属主与管理员都可以改。
- **改回公开**：同一个开关关掉即可。改回公开后，原来的公开链接立即可用。

[批量导入](./import.mdx)与 S3 兼容接口的上传不能指定私有；需要时导入或上传后再逐张设置。

## 生成签名链接 [#生成签名链接]

私有图片没有永久链接。要分享，先生成一条有时效的签名链接：

- **管理后台**：打开图片详情，选择有效期（1 小时、1 天、7 天、30 天），点「生成链接」，再按需要的格式复制。
- **接口**：`POST /api/admin/images/{id}/signed-url`，请求体 `{"ttl_seconds": 3600}`，有效期 1 秒到 365 天，返回带签名的完整链接和到期时刻。
- **上传响应**：私有上传的响应里，`url` 本身就是带签名的链接，到期时刻在 `expires_at`，默认有效 24 小时，用 `signed_ttl`（秒）指定。PicGo 这类直接取 `url` 的客户端不用改。

签名链接形如：

```
https://img.example.com/i/Ab3xK9?exp=1893456000&sig=hF3...
```

`exp` 是到期时刻（Unix 秒），`sig` 是对图片短 ID、图片的签名代次与到期时刻的 HMAC-SHA256 签名。签名代次随私有开关的每次变化加 1。链接后面可以照常加 `w`、`format` 等[处理参数](./access.mdx#on-demand-processing)，它们不参与签名。每次生成签名链接都会记入审计日志。

## 访问规则 [#访问规则]

| 请求 | 结果 |
|---|---|
| 公开链接，不带签名 | 404 |
| 签名被改动、图片 ID 对不上、`exp` 写法不规范，或私有开关变过之后用旧链接 | 404 |
| 签名正确，已过 `exp` | 404 |
| 签名正确，未到期 | 200，输出图片 |
| 管理后台的缩略图与预览 | 凭登录会话：属主与管理员可看，不需要签名 |
| S3 兼容接口的 GetObject、HEAD | 凭 S3 凭据，不受私有影响 |

所有「看不了」的情况都返回同样的 404，不区分图片不存在、没有签名与签名过期，避免探测者借此判断一张私有图是否存在。

通过 S3 对象键别名 `/o/<用户 id>/<对象键>` 访问私有图片同样需要签名：签名始终针对图片的短 ID，用该图的短 ID 生成。

## 与其他功能的关系 [#与其他功能的关系]

- **缓存**：响应带 `Cache-Control: private, no-store`，浏览器与 CDN 都不会保存。每次访问都回到本机校验签名。
- **302 直链**：私有图片即使在 `redirect` 访问模式下也由本机代理输出，不会重定向到渠道的公开地址。
- **按需处理**：签名链接可以带 `w`、`format`，衍生图只在本机缓存，不对外公开。
- **防盗链**：照常生效，签名有效不能绕过白名单。配置了防盗链并关闭「空 Referer 放行」时，直接在地址栏打开签名链接会被拒绝。
- **查重**：字节相同的图片合并为一份物理文件，私有与否按每条图片记录单独判断，公开的那条不受私有那条影响。
- **访问计数**：带有效签名的访问照常计数。
- **找回图片记录**：[找回](../operations/backup.mdx#找回图片记录)出来的图片都是公开的，渠道里的对象不记录私有标记，找回后需要把原本私有的图片重新设为私有。元数据库的备份与导出带有私有标记，恢复备份不受影响。

<Callout type="warn" title="签名链接防什么，不防什么">
- 防的是「链接被猜中、被爬取、被长期留存」：公开链接打不开，签名链接到期即失效。
- 不防持有人转发：有效期内拿到链接的人都能访问。需要更短的暴露窗口，就生成更短有效期的链接。
- 要在到期前收回已发出的链接：把图片改回公开再设为私有。私有开关每变一次，此前签发的链接全部失效；改回公开的那段时间里，公开链接是可以访问的。
- 先公开、后改成私有的图片，此前被浏览器或 CDN 缓存的副本，以及 `redirect` 模式下返回过的渠道直链，不会因此收回：公开期间的缓存最长一年，直链指向的渠道对象仍可访问。对已经公开过的图片，不要指望私有开关追回过去。
- 签名密钥由[主密钥](../configuration.mdx#主密钥)派生。更换主密钥会让所有签名链接失效，但这不是收回链接的办法，它会同时影响加密渠道，见主密钥一节。
- 私有图片不改变存储层：渠道里的对象还是明文（除非渠道开启了[存储加密](../channels/encryption.mdx)），能登录存储商账号的人看得到。
</Callout>
