### 内容库 内容库(或称“媒体库”)允许用户将文件上传到其本地通信服务器(homeserver)以供日后使用。例如,用户想要发送到房间的文件会上传至此,用户想要使用的头像也同样如此。 上传文件时,客户端会向用户本地通信服务器的特定资源发送 POST 请求,该资源会返回一个 `mxc://` URI,供日后通过 GET 请求进行下载。内容的下载则是从接收方的本地通信服务器完成,如果内容不是本地的,必须先通过同样的 API 从源通信服务器转存内容(除非源通信服务器和目的通信服务器为同一台服务器)。 在提供内容服务时,服务器应当提供 `Content-Security-Policy` 头。推荐的安全策略为: `sandbox; default-src 'none'; script-src 'none'; plugin-types application/pdf; style-src 'unsafe-inline'; object-src 'self';`。 {{% added-in v="1.4" %}} 当服务器向客户端提供内容时,还应当额外提供 `Cross-Origin-Resource-Policy: cross-origin` 头,以便(Web)客户端能够访问如 `SharedArrayBuffer` 等受限 API,在与媒体库进行交互时使用。 {{% changed-in v="1.11" %}} 未认证的下载端点已被弃用,建议使用新的、需要认证的端点。此更改包括将所有媒体端点的路径从 `/_matrix/media/*` 更新为 `/_matrix/client/{version}/media/*`,但 `/upload` 和 `/create` 端点除外。这两个上传/创建端点预计将在之后的版本中进行类似的迁移。 #### Matrix 内容(`mxc://`)URI 内容的位置以 Matrix 内容(`mxc://`)URI 形式表示。格式如下: ``` mxc:/// :内容最初上传所在的通信服务器名称,例如 matrix.org :用以标识内容的不透明 ID。 ``` #### 客户端行为 {id="content-repo-client-behaviour"} 客户端可通过以下端点访问内容库。 {{% changed-in v="1.11" %}} `/ _matrix/media` 层级下的多个端点已弃用并被新的、需要认证的端点取代。已弃用端点在下文中有注明。 {{% boxes/warning %}} 在 Matrix 1.12 版本,服务器应当“冻结”已弃用的非认证端点,以防止新上传的媒体被下载。这意味着冻结前上传的媒体仍可通过已弃用端点访问,而冻结后(或期间)上传的媒体应当只能通过新的认证端点访问。对于远程媒体,“新上传”由缓存填充时间决定。这意味着媒体本身可能早于冻结,但因服务器需重新下载,所以被视为“新媒体”。 客户端应当在服务器冻结非认证访问之前,更新以支持已认证的端点。 服务器在冻结前应充分考虑其本地生态影响。例如,确保用户常用客户端支持新端点,或者更新桥接程序以使用媒体代理等。 此外,[用于 `m.login.sso` 流程的 IdP 图标](/client-server-api/#definition-mloginsso-flow-schema) 应从冻结中排除。详情请参阅 `m.login.sso` 流程的架构说明。 服务器*示例*时间表如下: * Matrix 1.11 发行:客户端开始支持认证媒体访问。 * Matrix 1.12 发行:服务器冻结非认证媒体访问。 * 此前上传的媒体仍可通过弃用端点访问。 * 新上传(或缓存)的媒体*仅*能通过认证端点访问。 预计 Matrix 1.12 将于 2024 年 7~9 月正式发布。 {{% /boxes/warning %}} {{% http-api spec="client-server" api="authed-content-repo" %}} {{% http-api spec="client-server" api="content-repo" %}} ##### 缩略图 通信服务器应能够为上传的图片和视频生成缩略图。当前尚未规定支持生成缩略图的确切文件类型,详见 [Issue #1938](https://github.com/matrix-org/matrix-doc/issues/1938)。 缩略图方法分为“裁剪(crop)”和“缩放(scale)”。“scale”方法会返回宽度或高度小于请求尺寸的图片。客户端若需适配特定矩形尺寸,则需进一步缩放和留白补齐。“crop”方法则尽量返回与请求尺寸相近、并且保持请求尺寸宽高比的图片。客户端如需适配,也应进一步缩放图片以适配目标矩形。 传给缩略图 API 的尺寸为客户端期望的最小尺寸。服务器不得返回比客户端请求尺寸更小的缩略图,除非原始内容本身尺寸就小于请求尺寸。若原始内容尺寸较小,服务器应直接返回原始内容,而非额外生成缩略图。 服务器应生成以下尺寸、方法的缩略图: - 32x32,裁剪 - 96x96,裁剪 - 320x240,缩放 - 640x480,缩放 - 800x600,缩放 简要总结: - “缩放”会保持原始图片的宽高比 - “裁剪”会输出与请求尺寸宽高比一致的图片 - 服务器会尽量返回尺寸大于等于请求值的图片 服务器在任何情况下都不得对缩略图进行放大。除非原始内容尺寸不足,否则服务器也不得返回小于请求尺寸的缩略图。 #### 安全性考量 HTTP GET 端点无需认证。只要知道内容的 URL,无论实体是否在房间内都可获取内容。 `mxc://` URI 易遭目录遍历攻击,如 `mxc://127.0.0.1/../../../some_service/etc/passwd`。这可能导致目标通信服务器试图访问并返回该文件。因此,通信服务器必须对 `mxc://` URI 做合法性检查,仅允许在 `server-name` 和 `media-id` 中出现字母(A-Za-z)、数字(0-9)、下划线 `_` 和短横线 `-`。该白名单字符集兼容 RFC 4648 规范的 URL 安全 base64 编码。采用白名单优于黑名单(如黑名单排除 . 和 /),因为黑名单可能被漏洞(如百分号编码、UTF-8 编码遍历等)绕过。 通信服务器的内容服务还有额外的内容安全注意事项: - 客户端可能上传超大型文件。通信服务器应拒绝保存过大的文件,并返回 HTTP 413 且错误码为 `M_TOO_LARGE`。 - 客户端可能上传超大图片。通信服务器应拒绝为超大图片生成缩略图,返回 HTTP 413 并附带 `M_TOO_LARGE`。 - 远程通信服务器可能托管超大文件或图片。通信服务器应拒绝中转或生成超大远程文件/图片的缩略图,返回 HTTP 502 并附带 `M_TOO_LARGE`。 - 客户端可能尝试上传过多文件。通信服务器应限制单个客户端上传的文件数量与总大小,超过限制时返回 HTTP 403 并附带 `M_FORBIDDEN`。 - 客户端可能通过通信服务器访问大量远程文件。通信服务器应限制缓存的远程媒体的数量与总大小。 - 客户端或远程通信服务器可能上传包含针对通信服务器缩略图机制或客户端解码器漏洞的恶意文件。 ##### 内联内容服务 若客户端配置不安全,在以 `Content-Disposition: inline` 方式分发媒体时,可能会受到跨站脚本攻击。为降低大部分风险,客户端应避免与通信服务器的媒体端点部署在同一域名下。服务器应当在内联内容服务时,将 `Content-Type` 限定为以下值之一: * `text/css` * `text/plain` * `text/csv` * `application/json` * `application/ld+json` * `image/jpeg` * `image/gif` * `image/png` * `image/apng` * `image/webp` * `image/avif` * `video/mp4` * `video/webm` * `video/ogg` * `video/quicktime` * `audio/mp4` * `audio/webm` * `audio/aac` * `audio/mpeg` * `audio/ogg` * `audio/wave` * `audio/wav` * `audio/x-wav` * `audio/x-pn-wav` * `audio/flac` * `audio/x-flac` 在指定 `Content-Type` 时,上述类型不太可能引发跨站脚本风险,因为客户端只会按此类型渲染数据。例如上传 HTML 文件但指定类型为 `image/png` 时,客户端只会认为图片损坏,并不会作为 HTML 页面渲染。因此,只要 `Content-Disposition` 根据该类型正确计算,服务器即可信任用户定义的内容类型。 客户端不应依赖于服务器必定在 [`/download`](#get_matrixclientv1mediadownloadservernamemediaid) 接口返回 `inline` 而非 `attachment`。服务器实现可能出于安全考量将所有下载均返回 `attachment`,无论内容类型为何——客户端不应对此举感到意外。