链接式 Web 存储协议 1.0

W3C 工作草案

关于本文档的更多详细信息
此版本:
https://www.w3.org/TR/2026/WD-lws10-core-20260821/
最新发布版本:
https://www.w3.org/TR/lws10-core/
最新编辑草案:
https://w3c.github.io/lws-protocol/lws10-core/
历史:
https://www.w3.org/standards/history/lws10-core/
提交历史
编辑:
Jesse Wright牛津大学
Erich Bremer石溪大学
反馈:
GitHub w3c/lws-protocol拉取请求新建议题开放议题

摘要

Linked Web Storage Protocol 规范旨在以互操作的方式,为应用程序提供对外部存储数据的安全且经许可的访问。

本文档状态

本节描述本文档在发布时的状态。当前 W3C 出版物列表以及本技术报告的最新修订版可在 W3C 标准和草案 索引中找到。

这是一项非官方提案。

本文档由 Linked Web Storage 工作 组作为 工作草案发布,并使用 推荐标准 轨道

作为 工作草案发布并不意味着 W3C 及其成员认可该文档。

这是一份草案文档,可能随时被其他文档更新、替换或废弃。 除了作为正在进行中的工作外,不宜引用本文档。

本文档由一个按照 W3C 专利 政策运作的组制作。 W3C 维护着一份 与该组交付成果相关的任何专利披露的公开列表; 该页面还包含 披露专利的说明。实际 知晓某项专利且认为该专利包含 必要权利要求的个人 必须按照 W3C 专利政策第 6 节 披露相关信息。

本文档受 2025年8月18日 W3C 流程文档管辖。

1. 文档约定

本节为非规范性内容。

2. 引言

本规范定义了关联 Web 存储(LWS)协议,该协议使客户端应用程序能够根据代理的身份和权限访问和管理 Web 资源。

通过标准化资源服务器管理关联资源层次结构并提供其访问权限的方式,该 协议使用户能够使用不同的客户端应用程序与相同的已存储数据进行交互。这些 关联资源通过容器和包含关系进行定义,前者描述事物的 所在位置,后者以及元数据描述资源之间的相互关系。

该协议定义了对这些资源执行创建、读取、更新和删除的标准操作。每个 资源均由 URI 标识。客户端从根容器开始遍历资源层次结构, 并通过服务器响应中提供的链接发现其中包含的资源及其关系。

代理的身份通过身份提供方进行确认,该身份提供方可以位于关联 Web 存储 服务器之外。这种松耦合意味着服务器不一定直接管理凭据;相反,它 可以接收并验证由受信任身份 提供方作为令牌签发的已签名身份验证凭据。因此,用户可以向符合要求的服务器提供现有身份,而不必总是 仅为该服务器创建新账户或使用已有账户。例如,LWS 使用 OpenID Connect、SAML 2.0 和自签名受控标识符(CID)规范中定义的用户身份验证。

授权用于确定发出请求的代理是否有权访问资源或对其执行 操作。符合要求的 LWS 服务器为每个资源指定一个资源管理器,由其确定 资源是私有的(即仅可供其所有者使用)、受限的(即可供一组指定的 用户使用),还是公开的(即可供任何用户使用)。服务器在处理每个客户端请求时,会强制执行 资源管理器作出的访问决策。

本规范旨在供以下人员使用:

不同的 LWS 服务器实例各自维护其自身的关联资源层次结构。代理可以使用 相同的标识跨服务器进行遍历,而其对每台服务器资源的访问权限由该服务器的 资源管理器授予的权限决定。不能保证每个 LWS 服务器实例 都支持所有可能的代理标识符;任何给定的 LWS 服务器实例都可能要求代理 通过特定的身份提供方标识自身,以获得对该服务器 实例所管理资源的访问权限。

2.1 资源访问

LWS 协议定义了标准交互,某一方可通过这些交互向某些 代理提供某些资源。

2.2 安全和隐私

资源管理者可以将被服务资源 保持为私有,可以使其对任何人公开可用,或者可以将其可见性限制到一组受约束的 请求代理

2.3 一致性

除标记为非规范性的章节外,本规范中的所有创作指南、图表、示例和注释均为非规范性内容。 本规范中的其他所有内容均为规范性内容。

本文档中的关键词 MAYMUSTMUST NOTOPTIONALRECOMMENDEDREQUIREDSHOULDSHOULD NOT 应按 BCP 14 [RFC2119] [RFC8174] 中的描述解释,且仅当它们像这里所示以全 大写形式出现时才如此解释。

LWS 服务器是一个 HTTP 服务器 [rfc9112],它遵守 本规范中所有相关的“MUST”陈述。具体而言, 必须遵守本文档9. 操作中的相关规范性“MUST”陈述。

LWS 客户端是一个 HTTP 客户端 [rfc9112],它遵守本规范中所有相关的“MUST”陈述。具体而言,必须遵守本文档9. 操作中的相关规范性 “MUST”陈述。

2.4 作用域图

以下图表是与平台无关的模型, 用于指导实现。

图:系统上下文展示了 LWS 系统及其主要组件
1 系统上下文展示了 LWS 系统及其主要组件。

3. 术语

“授权服务器”和“客户端”这两个术语由 OAuth 2.0 授权框架 [RFC6749] 定义。

“最终用户”和“签发者”这两个术语由 OpenID Connect Core 1.0 [OPENID-CONNECT-CORE] 定义。

本规范定义了以下术语:

(存在风险的功能)问题: 本节可能会被移除

本规范定义了对所提供的 资源执行的操作、由此产生的状态变化,以及旨在向请求代理提供所请求信息或告知其 操作结果的响应操作是可以对所提供的资源执行的以下任一动作:

  • 创建资源 -
  • 读取 资源 -
  • 更新 资源 -
  • 删除 资源 -

下一节将描述这些操作的语义和响应,但以下核心 响应适用于任何操作:

  • 成功 - 认为操作已完成。该响应可以附带一个资源表示形式,用于传达所提供资源的内容。成功响应 不适用于创建资源操作。请改为参见已创建
  • 不 允许
  • 未知 请求者
  • 未知 错误 - 保留用于规范未预料到的 错误状况

4. 身份验证

本节定义了一种机制,用于标识与链接式 Web 存储服务器交互的代理和最终用户。 本规范并不强制要求身份验证凭证采用特定 格式,但它确实描述了如何将现有身份系统 与链接式 Web 存储授权框架结合使用。

4.1 身份验证 凭证数据模型

本节描述的数据模型概述了身份验证凭证的任何 具体序列化所需满足的要求。

身份验证凭证MUST 包含关于主体的防篡改声明,包括:

4.2 身份验证 凭证验证

身份验证凭证的验证需要凭证的 验证者和颁发者之间存在信任关系。此信任关系MAY 通过 带外机制建立。用于在验证者和颁发者之间建立信任的任何其他机制 均在特定的身份验证套件中概述。

身份验证凭证MUST 被签名。RECOMMENDED 使用非对称密码学 进行签名。

4.3 身份验证 凭证类型标识符

每个身份验证套件MUST 关联一个令牌类型 URI。身份验证套件SHOULD 使用 IANA “OAuth URI”注册表中定义的 URI。

5. 授权

Linked Web Storage 描述了一种在 Web 上持久化和管理受保护数据的机制。 授权是这样一种机制: 代理 通过它请求并呈现访问令牌,以访问这些受保护数据。

本节定义了一个基于 OAuth 2.0 [RFC6749] 的授权框架,作为 获取和呈现 访问令牌的基线机制。服务器MAY 支持此 基线之外的其他授权机制。

5.1 角色

LWS 授权中的角色与 OAuth 2.0 第 1.1 节 [RFC6749] 中定义的角色相同: 资源所有者资源服务器、 客户端(在本规范中称为授权客户端,以 避免歧义),以及 授权服务器。 存储服务器是一种同时符合 LWS 存储规范的资源服务器。

5.2 协议流程

本规范描述了客户端与授权服务器之间的交互,以及 客户端与合规存储服务器之间的交互。

授权服务器与存储服务器之间的交互不在本 规范范围内。 授权服务器可以与存储服务器是同一服务器,也可以是单独的实体。

5.2.1 授权服务器 发现

由存储服务器管理的所有受保护资源都需要由受信任 授权服务器生成的有效访问令牌。客户端可以通过向受保护资源发出 未授权的 HTTP 请求来发现受信任授权服务器的位置。

生成 401(未授权)响应的存储服务器MUST 发送一个 WWW-Authenticate 标头 字段,其中至少包含一个合规质询。合规质询将包含 下述参数:

  • as_uri REQUIRED — 此 参数的值是一个 URI,用于标识授权服务器, 客户端可在该授权服务器处获取访问令牌。此参数的值将与 有效访问令牌的 iss 声明相同。
  • realm REQUIRED — 此 参数的值是一个 URI,表示保护范围。 此值将包含在访问令牌的 audience(aud)声明中。 客户端MUST 验证 发起请求的 URI 在逻辑上包含于此响应中呈现的 realm 之内。

可以包含其他标头和参数。

下面包含一个 401 响应示例。

HTTP/2 401 Unauthorized
Link: <https://storage.example/storage_1>; rel="https://www.w3.org/ns/lws#storage"
WWW-Authenticate: Bearer as_uri="https://authorization.example",
                realm="https://storage.example/storage_1",
                error="invalid_token"

5.2.2 授权服务器 元数据

授权服务器MUST 提供一个元数据资源,以允许客户端 按照 [RFC8414] 中的描述 发现端点位置和能力。此元数据资源 MUST 可在路径为 /.well-known/lws-configuration 的 URL 处获得。

授权服务器SHOULD 通过在服务器元数据文档中包含 subject_token_types_supported 条目,宣告其支持的主体令牌。此条目是一个 JSON 数组,其中包含可在 授权服务器令牌端点提供的有效 subject_token_type 值列表。

下面包含一个授权服务器元数据资源示例。

{
    "issuer": "https://authorization.example",
    "grant_types_supported": [
        "urn:ietf:params:oauth:grant-type:token-exchange"],
    "token_endpoint": "https://authorization.example/token",
    "jwks_uri": "https://authorization.example/jwks",
    "claims_supported": [
        "sub",
        "iss",
        "client_id",
        "aud"],
    "response_types_supported": [
        "token"],
    "subject_token_types_supported": [
        "urn:ietf:params:oauth:token-type:jwt",
        "urn:ietf:params:oauth:token-type:id-token"]
}

5.2.3 令牌交换

LWS 授权服务器是一个合规的 OAuth 2.0 授权服务器,能够向客户端颁发 访问令牌, 以供存储服务器使用。为了颁发访问令牌,客户端必须首先通过 OAuth 2.0 Token Exchange [RFC8693] 向授权服务器呈现有效的主体令牌, 例如身份验证凭证

5.2.3.1 请求

授权服务器的令牌端点MUST 支持 urn:ietf:params:oauth:grant-type:token-exchange 授权类型,如 OAuth 2.0 Token Exchange [RFC8693] 中所述。

执行令牌交换授权类型时,适用以下附加要求:

  • resource 参数是REQUIRED。此 参数的值MUST 是 URI,并将用于填充所得访问令牌中的 aud(受众)声明。提供的值将与 WWW-Authenticate 质询中的 realm 参数响应相同。授权服务器 MUST 拒绝任何 resource 参数标识 未知或不受信任存储的请求。
  • subject_token 参数是REQUIRED。此 参数的值MUST 包含有效的主体令牌, 例如身份验证 凭证
  • 在向客户端返回访问令牌之前,授权服务器MUST 成功验证所有呈现的令牌。

令牌请求的非规范性示例(subject_token 参数已被 截断)。

POST /token HTTP/1.1
Host: authorization.example
Content-Type: application/x-www-form-urlencoded

grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Atoken-exchange
&resource=https%3A%2F%2Fstorage.example%2Fstorage_1
&subject_token=eyJ0eXAiOiJhcytqd3QiLCJhbGciO...fiK51VwhsxJ-siBMR-YFiA
&subject_token_type=urn%3Aietf%3Aparams%3Aoauth%3Atoken-type%3Aid_token
5.2.3.2 响应

如果令牌请求有效且客户端被授权发出该请求,则 授权服务器响应MUST 符合 OAuth 2.0 Authorization Framework [RFC6749] 第 5.1 节。所得访问 令牌MUST 符合 JSON Web Token Profile for OAuth 2.0 Access Tokens [RFC9068]。

此外,访问令牌必须满足以下要求:

  • sub(主体)— REQUIRED。此声明 MUST 是标识执行 操作的代理的 URI
  • iss(颁发者)— REQUIRED。此声明 MUST 是授权服务器的 URI
  • client_id(客户端 id)— REQUIRED。 此声明MUST 是标识客户端的 URI。
  • aud(受众)— REQUIRED。此声明 MUST 包含客户端 在 resource 参数中提供的 URI。此值将用于限制访问令牌对哪些实体 有效。它将 与存储服务器在 WWW-Authenticate 质询的 realm 参数中提供的值 相同。
  • exp(过期时间)— REQUIRED。 授权服务器SHOULD 颁发短生命周期的令牌 (RECOMMENDED:300 秒或更短),以限制令牌 被盗造成的暴露。
  • iat(签发时间)— REQUIRED
  • jti(JWT ID)— REQUIRED

下面包含一个成功令牌响应的非规范性示例。

HTTP/1.1 200 OK
Content-Type: application/json

{
    "access_token":"eyJ0eXAiOiJhcytqd3QiLCJhbGciOiJFUzI1NiIs...DeWt4QuZXso",
    "token_type":"Bearer",
    "expires_in":3600
}

所有无效或未授权的请求MUST 产生错误响应, 如 OAuth 2.0 Authorization Framework [RFC6749] 第 5.2 节中所述。

HTTP/1.1 400 Bad Request
Content-Type: application/json

{
    "error":"invalid_request"
}
5.2.3.3 访问令牌示例

本节为非规范性内容。

下面包含一个由授权服务器颁发的访问令牌示例。

{
  "kid": "ec51c6b2",
  "kty": "EC",
  "alg": "ES256",
  "crv": "P-256",
  "typ": "at+jwt"
}
.
{
  "sub": "https://id.example/agent",
  "iss": "https://authorization.example",
  "client_id": "https://app.example/id",
  "aud": "https://storage.example",
  "exp": 1735686300,
  "iat": 1735686000,
  "jti": "550e8400-e29b-41d4-a716-446655440000"
}
.
signature

5.2.4 存储服务器进行的令牌验证

一旦客户端拥有访问令牌,它就会将此令牌呈现给存储服务器。 存储服务器负责在执行任何操作之前验证此令牌。

5.2.4.1 呈现

客户端MUST 使用 Authorization 标头 以及 [RFC6750] 中定义的身份验证方案, 向存储服务器呈现访问令牌。

Authorization: Bearer eyJ0eXAiOiJhcytqd3QiLCJhbGciOiJFUzI1NiIs...DeWt4QuZXso
5.2.4.2 验证

存储服务器MUST 通过执行 以下检查来验证访问令牌,并在任何检查失败时拒绝请求:

  • JWT 签名验证:使用从授权服务器元数据中指定的 jwks_uri 获取的授权服务器公钥来验证 JWT 签名。存储服务器SHOULD 缓存这些密钥,并且 MUST 支持密钥轮换。
  • 颁发者验证:验证 iss 声明与预期的授权 服务器标识符匹配。
  • 受众验证:验证 aud 声明恰好包含一个值,并且该 值是标识在逻辑上包含目标资源的存储服务器的 URI。
  • 时间验证,受系统之间允许的时钟偏差约束。
    • 验证当前时间早于 exp(过期时间)声明。
    • 如果存在 nbf(不早于)声明,验证当前时间不早于该声明。
    • 验证 iat(签发时间)声明不在未来。

如果验证失败,存储服务器MUST 返回 401 Unauthorized, 并带有 WWW-Authenticate 标头, 其中包含适当的 error 参数(例如 invalid_token、invalid_request 或 insufficient_scope)。

如果令牌在其他方面有效,但授权策略不允许所请求的 操作, 则存储服务器MUST 拒绝该请求。

6. 发现

6.1 存储描述资源

存储描述资源提供 客户端在与存储交互时可使用的信息,包括能力和 服务端点的描述。

6.1.1 数据模型

存储描述资源W3C 受控标识符 文档 [CID-1.0] 的一种特化形式。 它符合 [CID-1.0] 定义的数据模型,并通过 LWS 特有的属性进行了扩展。

  • id - id 属性是必需的。其值必须存储的规范 URI。 根据 [CID-1.0],此 URI 也是受控标识符文档的规范 URL。
  • type - type 属性是必需的。其值必须是一个等于 Storage 的字符串,或一个包含等于 Storage 项的字符串集合 (区分大小写)。
  • capability - capability 属性是可选的。其值必须是一个 能力集合,其中每项能力均由包含以下属性的映射描述。 还可以存在其他属性。
    • id - id 属性是可选的。如果存在,其值必须 是 URI。
    • type - type 属性是必需的。其值必须是一个字符串 或字符串集合。
  • service - service 属性是必需的。其值必须是一个服务集合, 其中每项服务均由包含以下属性的映射描述。还 可以存在其他属性。 该集合必须包含一个 type 等于 StorageRoot 的服务。
    • id - id 属性是可选的。如果存在,其值必须 是 URI。
    • type - type 属性是必需的。其值必须是一个字符串 或字符串集合。
    • serviceEndpoint - serviceEndpoint 属性是必需的。其值必须 是 URI。
示例 8:最小存储描述资源
{
  "@context": [
    "https://www.w3.org/ns/cid/v1",
    "https://www.w3.org/ns/lws/v1"
  ],
  "id": "https://storage.example/",
  "type": "Storage",
  "service": [{
    "type": "StorageRoot",
    "serviceEndpoint": "https://storage.example/root/"
  }]
}

6.1.2 发现和绑定

针对存储资源的所有 GETHEAD 请求的响应必须包含一个 Link 标头,其目标为该存储的规范 URI,并包含一个 值等于 https://www.w3.org/ns/lws#storage 的关系 (rel) 参数。

存储 URI 的请求必须返回一个 符合 存储描述资源数据模型且 媒体类型为 application/lws+cid 的文档, 除非内容协商要求使用其他格式。

6.1.3 存储能力

存储描述可以包含对存储所支持的其他能力的描述。

6.1.4 存储服务

存储描述资源必须包含一个 StorageRoot 服务,其 serviceEndpoint存储根容器的 URI。 还可以存在与存储关联的其他服务。 这些附加服务的 API 定义不在本规范的范围内。

6.1.5 存储 描述表示

存储描述必须能够使用媒体类型 application/lws+cid 进行序列化。 @context 属性必须是一个以 URI https://www.w3.org/ns/cid/v1https://www.w3.org/ns/lws/v1 开头的数组。 其他表示形式可以通过内容协商提供。

示例 9:存储描述资源
{
  "@context": [
    "https://www.w3.org/ns/cid/v1",
    "https://www.w3.org/ns/lws/v1"
  ],
  "id": "https://storage.example/",
  "type": "Storage",
  "capability": [{
    "type": "https://feature.example/PatchSupport",
    "format": {
      "text/turtle": ["application/sparql-update"],
      "application/n-triples": ["application/sparql-update"],
      "application/linkset+json": ["application/merge-patch+json", "application/json-patch+json"]
    }
  }, {
    "type": "https://feature.example/ResumableUploads"
  }, {
    "type": "https://feature.example/ContentNegotiation",
    "source": "application/ld+json",
    "target": ["text/turtle", "application/n-triples"]
  }, {
    "type": "https://feature.example/ContentNegotiation",
    "source": "image/jpeg",
    "target": ["image/png"]
  }],
  "service": [{
    "type": "StorageRoot",
    "serviceEndpoint": "https://storage.example/root/"
  }, {
    "type": "NotificationService",
    "serviceEndpoint": "https://storage.example/notification/api",
    "subscriptionType": ["WebhookSubscription"]
  }, {
    "type": "TypeIndexService",
    "serviceEndpoint": "https://storage.example/types/index"
  }, {
    "type": "TypeSearchService",
    "serviceEndpoint": "https://storage.example/types/search"
  }, {
    "type": "DataSharingService",
    "serviceEndpoint": "https://storage.example/sharing/api"
  }]
}

7. 逻辑资源组织

7.1 容器模型

关联 Web 存储将资源组织到容器中。容器是一种 专门的资源,它保存对其他资源的引用,这些资源称为其成员。容器充当 组织单元,类似于目录或集合,使客户端能够对资源进行分组、发现 和导航。容器维护对其成员资源的引用, 这些资源可能同时包括非容器资源和其他容器资源,从而能够形成 层次结构。通常,除了元数据或其成员的枚举之外,容器 几乎不包含固有内容;其主要作用是聚合和组织 下级资源。存储系统的根被指定为容器,充当 没有上级父项的最高层组织单元。容器表示的结构在8.1 容器 表示中定义;其媒体类型和分页要求在12. LWS 媒体类型中定义。 存储可以充当根容器,从而允许直接写入。

每个 LWS 存储都有一个存储 根,它充当顶级组织单元。存储根没有父项,并充当存储 层次结构的入口点。

LWS 中的资源被分类为以下两类之一:

7.2 包含关系

资源与其父容器之间的包含关系通过 rel="up" 链接 关系表示。对于任何 非根资源上的 GET 和 HEAD 请求,服务器MUST 在响应中包含一个 Link 标头,其中 rel="up" 指向父容器。

Link: </alice/notes/>; rel="up"

容器的成员在其表示中使用 items 属性列出。服务器管理此列表;客户端不能直接修改它。成员关系 变更作为资源创建和删除的副作用发生。

7.3 包含关系完整性

服务器MUST 始终维护包含关系完整性:

7.4 资源标识

资源由 URI 标识。资源的 URI 与其在包含关系层次结构中的位置无关。服务器在创建资源时分配 URI, 并且可以采用客户端提示,但客户端不应该假定 URI 结构反映了包含关系。

包含关系通过元数据表示 (rel="up" 链接和容器 表示中的 items 属性),而不是通过 URI 路径结构表示。这种分离允许服务器在 URI 分配方面具有灵活性,同时维护一个定义良好的组织模型。

7.5 容器成员关系 和授权

如果客户端对容器具有读取访问权限,则容器 表示MUST 包含该容器中客户端有权访问的所有资源的标识符。它MAY 也包含该容器中客户端无权访问的资源的标识符。

客户端读取容器列表的能力,并不意味着其可访问所包含的 资源本身,反之亦然。

8. 容器

8.1 容器表示

当客户端检索容器时,服务器会返回一个结构化的容器表示,用于描述该容器及其内容。本节定义容器表示的必需和 可选属性。

8.1.1 容器属性

容器表示MUST 包含以下属性:

  • id容器的 URI。
  • type:值为 "Container"
  • totalItems:一个整数,表示 容器中可向客户端披露的资源总数。此 计数SHOULD 准确,但MAY 是 近似值。
  • items:被包含资源描述的数组(见下文)。如果 容器为空,则此项MUST 是 空数组。当容器列表 分页时,items 仅包含当前页的资源;详情见分页

8.1.2 被包含资源 描述

items 数组中的每个条目描述容器中包含的一个资源。被包含资源描述MUST 包含:

  • id:被包含资源的 URI。
  • type:资源的类型。MUST"DataResource""Container",或是至少包含 这两个字符串之一的数组。服务器MAY 包含其他用户定义类型作为 URI(例如 ["DataResource", "http://example.org/customType"])。

被包含资源描述SHOULD 包含:

  • format:资源的媒体类型(例如 "text/plain""image/jpeg")。对于 DataResources, MUST 存在此项。
  • size:资源的大小,以字节为单位,以整数表示。
  • modified:资源最后修改的日期和时间, 表示为 ISO 8601 日期时间字符串。

8.1.3 容器 表示示例

以下示例显示位于 /alice/notes/ 的一个容器,其中包含两个 资源:

{
  "@context": "https://www.w3.org/ns/lws/v1",
  "id": "/alice/notes/",
  "type": "Container",
  "totalItems": 2,
  "items": [
    {
      "type": "DataResource",
      "id": "/alice/notes/shoppinglist.txt",
      "format": "text/plain",
      "size": 47,
      "modified": "2025-11-24T12:00:00Z"
    },
    {
      "type": ["DataResource", "http://example.org/customType"],
      "id": "/alice/notes/todo.json",
      "format": "application/json",
      "size": 2048,
      "modified": "2025-11-24T13:00:00Z"
    }
  ]
}

9. 操作

本节定义 Linked Web Storage(LWS)服务器MUST 支持的四种核心操作。这些操作以 传输无关的方式操纵资源和容器,侧重于语义而不是实现细节。每个操作 都指定输入、预期行为和可能的响应。响应包括成功指示符、资源 表示(在适用时)和错误条件。实现MUST 以原子且一致的方式处理这些操作,这意味着每个操作要么完全成功,要么 失败且没有部分副作用。发生错误时,响应SHOULD 提供 足够细节,使代理能够理解问题,同时不泄露敏感信息。

对于每个核心操作(创建、读取、更新、删除),我们描述要使用的 HTTP 方法、所需 标头或特殊考量(包括通过 ETag 进行并发控制、内容协商,以及 容器列表的分页),以及服务器应执行和返回的内容。标准 HTTP 状态码 用于指示结果,并为诸如配额超出(507 Insufficient Storage)或前提条件失败(412 Precondition Failed)等场景提供额外映射。 该绑定尝试遵循 HTTP/1.1 和 相关 RFC(例如 [RFC7231] 用于 HTTP 语义,[RFC7233] 用于范围 请求,[RFC5789] 用于 PATCH,[RFC8288] 用于 Web Linking, 以及 [RFC9264] 用于 Link Sets),以便它自然地与 Web 标准集成。可发现性通过 诸如 401 响应上的 Link 标头和 WWW-Authenticate 标头等机制得到强调, 避免硬编码 URI 位置。各操作都要求元数据 集成,确保原子性,并使用 Link Sets 表示服务器管理和 用户管理的属性。

注:与本规范中的所有示例一样,本节给出的示例(HTTP 请求 和响应片段)均为非规范性内容,旨在说明典型用法。实际 要求在说明性文本和表格中陈述。此外,虽然此绑定涵盖 HTTP(作为 初始目标协议),但原则上未来可以将 LWS 操作绑定到其他协议。 容器表示的媒体类型要求在12. LWS 媒体类型中定义。

9.1 元数据

本节定义了将元数据与LWS 资源关联的模型。 LWS 元数据系统基于 Web 链接 [RFC8288] 的原则,该原则 允许服务器使用类型化链接描述资源之间的关系。元数据增强了 可发现性,支持自描述 API,并与资源操作及容器层次结构保持一致。

元数据模型 LWS 中的所有元数据都表示为一组源自某个资源(链接上下文)的类型化链接。 每个链接包括:

元数据区分资源及其表示,从而在适用时允许使用多种媒体类型。 对于数据资源,元数据包括多个表示,每个表示都带有 format 和可选的 sizeInBytes。对于容器数据资源,我们将指向 其父容器资源的链接视为该资源元数据的一部分。

链接集资源 对于存储中的每个资源,服务器必须按照 [RFC9264] 将元数据链接 作为独立资源提供。

发现元数据 客户端主要通过 GET 或 HEAD 请求响应中的 Link 标头发现元数据。

元数据类型

类别 描述
系统管理 由服务器维护;只读。包括 linksettypeformatsizemodified
核心元数据 由客户端管理(受服务器限制)。包括 upitemstitlecreator
用户定义 由用户创建的自定义词汇表和索引。

可修改性注意事项 核心元数据可以由客户端修改。为确保互操作性,服务器 必须使用标准 HTTP 标头公布其能力:

  1. 方法发现:服务器必须通过 Allow 标头公布对链接集资源执行 GET 和 PATCH 操作的支持。

  2. 补丁格式发现:服务器必须通过 Accept-Patch 标头公布对 JSON 合并 补丁 [RFC7386] 的支持: Accept-Patch: application/merge-patch+json

  3. 可选方法:服务器可以支持 PUT 或其他补丁格式; 如果支持,则这些方法和格式必须分别包含在 Allow 和 Accept-Patch 标头中。

[!重要] 除非资源标头中公布了对 PUT 或特定补丁格式的支持,否则客户端不应该假定支持它们,并且必须妥善处理 405 方法 不允许或 415 不支持的媒体类型响应。

管理元数据 元数据通过与资源关联的链接集资源 URI 进行交互来管理。服务器必须支持更新的并发控制。

9.2 创建资源

创建资源操作将一个新的被服务资源添加到现有容器中。此 操作同时处理数据资源和子容器的创建。

输入:

行为:

可能的响应:

使用 POST 向目标容器 URI 创建新资源,由服务器分配 最终标识符。客户端可以通过在 POST 请求中包含一个或多个 Link 标头,按照 [RFC8288] 中 Web 链接的语法,为新资源提供初始的用户管理元数据。 服务器管理的元数据必须 由服务器在创建时自动生成,并且不得 被客户端提供的链接覆盖。

成功后,服务器必须返回 201 状态码,并在 Location 标头中提供新 URI。服务器必须包含用于 关键服务器管理元数据的 Link 标头,其中包括指向父容器的链接 (rel="up"),以及指向所创建资源专用链接集资源的链接 (rel="linkset"; type="application/linkset+json")。其他链接应该包括 rel="type"(指示 https://www.w3.org/ns/lws#Containerhttps://www.w3.org/ns/lws#DataResource)。响应主体可以为空,也可以 包含资源的最小表示。所有元数据的创建和链接必须与资源创建以原子方式进行,以保持一致性。

POST(向容器 URI)使用服务器分配的名称创建: 使用 POST 在现有容器内添加新资源。服务器为资源分配 标识符。客户端按如下方式指示要创建的资源类型:

示例(使用 POST 创建新的数据资源):

POST /alice/notes/ HTTP/1.1
Host: example.com
Authorization: Bearer <token>
Content-Type: text/plain
Content-Length: 47

milk
eggs
bread
butter
apples
orange juice

在此示例中,客户端正在向容器 /alice/notes/ 发送 POST 请求。它 提供 text/plain 内容(一份购物清单),并为新资源建议名称 shoppinglist.txt。如果 /alice/notes/ 存在且客户端 已获得授权,服务器将创建新的数据资源,并将其添加到该容器的成员中。

示例(对 POST 的响应 — 数据资源):

HTTP/1.1 201 Created
Location: /alice/notes/shoppinglist.txt
Content-Type: text/plain; charset=UTF-8
Link: </alice/notes/shoppinglist.txt.meta>; rel="linkset"; type="application/linkset+json"
Link: </alice/notes/>; rel="up"
Link: <https://www.w3.org/ns/lws#DataResource>; rel="type"
Content-Length: 0

成功后,返回 201 Created,并在 Location 标头中提供新 URI。响应主体可以 为空,也可以是最小表示。 如果目标容器 /alice/notes/ 不存在,服务器 必须返回 404 错误状态,除非其他状态码更为适当。

创建容器要创建新的容器,客户端使用 POST 向现有父容器发送请求,并使用 Link 标头指示 容器类型。例如:

POST /alice/ HTTP/1.1
Host: example.com
Authorization: Bearer <token>
Content-Length: 0
Link: <https://www.w3.org/ns/lws#Container>; rel="type"

示例(对 POST 的响应 — 容器):

HTTP/1.1 201 Created
Location: /alice/notes/
Link: </alice/notes/.meta>; rel="linkset"; type="application/linkset+json"
Link: </alice/>; rel="up"
Link: <https://www.w3.org/ns/lws#Container>; rel="type"
Content-Length: 0

这将在 /alice/notes/ 创建新的容器,其中由服务器生成的 元数据包括值为 https://www.w3.org/ns/lws#Containerrel="type"

有关创建操作的其他说明(HTTP 绑定):

管理和检索元数据(与创建相关): 尽管元数据主要通过读取操作检索,但它是在创建过程中生成的。客户端可以 在创建后立即对新资源 URI 使用 GET 或 HEAD 来检索元数据。客户端可以使用 Prefer 标头请求包含特定的元数据链接(通过关系类型)和 属性。

9.3 读取资源

检索现有资源的表示,或容器的列表。

读取资源操作通过 HTTP GET 请求(以及用于仅获取标头请求的 HEAD) 请求资源表示。行为取决于目标 URL 是容器还是非容器资源(数据资源)。服务器MUST 通过元数据区分资源类型。所有响应MUST 与 第 8.1 节定义的元数据集成,包括用于关键关系的 Link 标头,例如 rel="linkset"rel="up"rel="type"。服务器MUST 确保读取期间资源状态与其元数据之间的原子性。

GET(非容器资源)检索资源内容: 向资源 URI 发送 GET 以获取完整内容(如果已获授权)。以 200 OK 响应,正文包含 数据,Content-Type 与所存储的媒体类型匹配。服务器MUST 按照 [RFC7233] 支持 范围请求,以便部分检索。响应MUST 包含 ETag 标头,用于并发控制和 缓存。

示例(GET 一个文件):

GET /alice/notes/shoppinglist.txt HTTP/1.1
Authorization: Bearer <token>
Accept: text/plain

这会请求 /alice/notes/shoppinglist.txt 的内容,表明客户端希望 以文本形式获取它。假定资源存在、是文本,并且客户端有权访问:

HTTP/1.1 200 OK
Content-Type: text/plain; charset=UTF-8
Content-Length: 34
ETag: "abc123456"
Link: </alice/notes/shoppinglist.txt.meta>; rel="linkset"; type="application/linkset+json"
Link: </alice/notes/>; rel="up"
Link: <https://www.w3.org/ns/lws#DataResource>; rel="type"

milk
cheese
bread
guacamole
soda
chocolate bars
hash
eggs

服务器返回了文本内容(共 34 字节,如 Content-Length 所示)。 内容正是该文件中存储的数据。ETag: "abc123456" 是用于缓存或并发目的的版本 标识符。响应包含用于元数据 可发现性的 Link 标头,并带有 uptype 等强制字段。

GET(容器资源)列出容器内容: 当目标 URI 对应于容器(通过元数据类型确定)时,GET 请求返回该 容器成员的列表。响应正文是 容器表示,如容器表示一节所定义,使用 LWS 容器媒体 类型。该列表包括每个成员的元数据:资源标识符(MUST)、类型(MUST)、媒体类型(对于 DataResources,MUST)、大小(SHOULD)以及 修改时间戳(SHOULD)。

示例(GET 一个容器):

GET /alice/notes/ HTTP/1.1
Authorization: Bearer <token>
Accept: application/lws+json

假定容器存在且客户端有权访问:

HTTP/1.1 200 OK
Content-Type: application/lws+json
ETag: "container-etag-789"
Link: </alice/notes/.meta>; rel="linkset"; type="application/linkset+json"
Link: </alice/>; rel="up"
Link: <https://www.w3.org/ns/lws#Container>; rel="type"

{
  "@context": "https://www.w3.org/ns/lws/v1",
  "id": "/alice/notes/",
  "type": "Container",
  "totalItems": 2,
  "items": [
    {
      "type": "DataResource",
      "id": "/alice/notes/shoppinglist.txt",
      "format": "text/plain",
      "size": 47,
      "modified": "2025-11-24T12:00:00Z"
    },
    {
      "type": ["DataResource", "http://example.org/customType"],
      "id": "/alice/notes/todo.json",
      "format": "application/json",
      "size": 2048,
      "modified": "2025-11-24T13:00:00Z"
    }
  ]
}

在此示例中,/alice/notes/ 是一个容器。响应使用带有 LWS 上下文的 JSON-LD,列出带有必需元数据的成员。每个条目都包含其 typeidformatsizemodified 时间戳作为扁平 属性。

在所有情况下,服务器MUST 在响应 标头中包含以下元数据:ETag(表示列表版本,它会在成员关系修改时变化),以及 Link 标头,其中 rel="type" 表明它是一个容器,并包含 rel="linkset"rel="up"

HEAD(任何资源或容器仅标头/元数据: LWS 服务器MUST容器和非容器均支持 HEAD [RFC9110], 返回与 GET 相同的标头(包括 ETag、Content-Type、用于元数据的 Link),但没有正文。这可以在不传输内容的情况下检索 元数据。

缓存和条件请求:LWS 利用 HTTP 缓存语义。服务器MUST 支持通过 If-None-Match(使用 ETag)或 If-Modified-Since 标头进行条件请求。如果资源或容器列表未更改,则响应 304 Not Modified,以避免冗余传输。所有 GET/HEAD 响应中MUST 提供 ETag, 用于并发和缓存支持。

可发现性和授权:为了增强可发现性,服务器SHOULD 在 401 Unauthorized 响应上包含带有 参数的 WWW-Authenticate 标头,以便在没有硬编码 URI 的情况下引导客户端。元数据链接SHOULD 在适用时包含。

9.4 更新资源

通过完整替换或部分补丁修改现有 [served resource] 的状态。

更新资源通过 PUT 请求(替换整个资源)或 PATCH 请求(应用 部分修改)修改现有被服务 资源的内容。客户端必须对资源 URL 拥有写访问权限才能执行这些 操作。 注:本节描述更新资源的主要内容。要更新其元数据,请见第 9.3.2 节。 LWS 服务器MUST 将资源 URI 上的 PUT 和 PATCH 请求处理为 仅对资源内容的修改,默认情况下不影响关联的linkset 资源。为了可选择地在单个原子操作中同时更新内容和 元数据,客户端MAY 在对资源 URI 的 PUT/PATCH 请求中包含 Link 标头,并指定偏好 'Prefer: set-linkset'(如 RFC 7240 中所定义)。在这种情况下,服务器MUST 将提供的 Link 标头解释为 对 linkset 的替换(对于 PUT)或部分更新(对于 PATCH),并同时应用 内容更改。此行为对服务器而言是OPTIONAL,但如果支持,MUST 通过 Prefer 标头显式调用,以防止无意 覆盖元数据。不支持组合更新的服务器MUST 忽略 该偏好或以 501 Not Implemented 响应。

PUT(替换完整资源) – 向资源 URI 发送 PUT,并在 正文中包含新的完整内容和匹配的 Content-Type(通常与现有类型一致)。PUT 对现有 资源是幂等的。为安全起见,包含带有当前 ETag 的 If-Match(依据第 7.3 节并发);不匹配会产生 412 Precondition Failed 或 409 Conflict。如果没有检查,更新是无条件的,但可能覆盖 并发更改。如果服务器支持资源的 Etags,它MUST 以 428 Precondition Required 响应拒绝缺少 If-Match 标头的无条件 PUT 请求。

示例(PUT 更新资源):

PUT /alice/personalinfo.json HTTP/1.1
Authorization: Bearer <token>
Content-Type: application/json
If-Match: "abc123456"
{
"name": "Alice",
"age": 30,
"city": "New London",
"state": "Connecticut"
}

在此示例中,客户端正在更新 /alice/personalinfo.json 处的现有 JSON 资源。它 包含一个 If-Match 标头,其中带有它从早先 GET 或 HEAD 请求获得的 ETag "abc123456"。 服务器会将其与当前 ETag 比较;如果匹配,就继续用 所提供的 JSON 替换内容。如果不匹配,服务器会拒绝更新(因为该资源在此期间 已被其他人更改)。 成功响应:如果更新成功,服务器可以用 200 OK 响应,并可能包含 更新后的表示或某些确认信息(例如新内容或其中一部分)。或者, 服务器可以用 204 No Content 响应,表示成功但无正文(如果无需传达更多 信息,这尤其常见)。无论哪种情况,服务器SHOULD 包含新的 ETag 来表示新版本,如果返回正文,也可以包含 Content-Type。例如:

HTTP/1.1 204 No Content
ETag: "def789012"

这会告诉客户端更新已完成,并提供新的 ETag。如果服务器选择 返回更新后的内容,它可能使用 200 OK 并在正文中包含 JSON,同时 带有标头。

PATCH(部分更新) – HTTP PATCH 方法 [RFC5789] 允许客户端指定对资源的部分修改,而不是发送完整的新 内容。当资源很大且只有一小部分发生变化时,发送整个内容效率较低, 或者在并发编辑中希望应用特定更改时,这很有用。LWS 服务器MUST 至少支持 [RFC7386] 中定义的 JSON Merge Patch(application/merge-patch+json)。

更新资源元数据(对 Linkset 使用 HTTP PUT / PATCH) 资源的元数据通过修改其对应的linkset 资源来更新, 该资源通过带有 rel="linkset" 的 Link 标头发现。 完整替换(PUT):对linkset 资源 URI 发送 PUT 请求,并在正文中包含完整 linkset 文档,会替换该资源的所有元数据。 部分更新(PATCH):对linkset 资源 URI 发送 PATCH 请求,会添加、移除或 修改特定链接。

元数据的并发控制 因为资源的元数据可能由多个参与者修改,防止并发覆盖至关重要。 为确保数据完整性,LWS 服务器和客户端MUST 为所有 对linkset 资源的 PUT 和 PATCH 操作,实现使用条件请求 [RFC7232] 的乐观并发控制。 服务器职责: 服务器MUST 在其对linkset 资源的 GET 和 HEAD 请求响应中包含 Etag 标头。 在成功对 linkset 执行 PUT 或 PATCH 后,服务器MUST 为修改后的 linkset 生成新的、 唯一 Etag 值,并在响应的 Etag 标头中返回它。 客户端职责: 修改linkset 资源时,客户端MUST 包含一个 If-Match 标头,其中包含它最近收到的该资源 Etag。 处理规则: 如果 If-Match 标头值与 linkset 的当前 Etag 不匹配,服务器MUST 以 412 Precondition Failed 状态码拒绝请求。 如果对 linkset URI 的 PUT 或 PATCH 请求缺少 If-Match 标头,服务器MUST 以 428 Precondition Required 状态码拒绝请求 [RFC6585]。 示例(PUT 替换 linkset): 客户端首先获取 linkset 并接收其 ETag。

GET /alice/personalinfo.json.meta HTTP/1.1
Authorization: Bearer <token>
Accept: application/linkset+json
HTTP/1.1 200 OK
Content-Type: application/linkset+json
ETag: "meta-v1"
{
  "linkset": [
    {
      "anchor": "/alice/personalinfo.json",
      "describedby": [ { "href": "/schemas/personal-info.json" } ]
    }
  ]
}

客户端现在想要添加许可证。它构造一个新的完整 linkset 文档,并发送带有 If-Match 标头的 PUT 请求。

PUT /alice/personalinfo.json.meta HTTP/1.1
Authorization: Bearer <token>
Content-Type: application/linkset+json
If-Match: "meta-v1"
{
  "linkset": [
    {
      "anchor": "/alice/personalinfo.json",
      "describedby": [ { "href": "/schemas/personal-info.json" } ],
      "license": [ { "href": "https://creativecommons.org/licenses/by/4.0/" } ]
    }
  ]
}

如果成功,服务器以成功响应,并返回新的 ETag。

HTTP/1.1 204 No Content
ETag: "meta-v2"

更新规则摘要 如果你只想更改资源的内容 → 对资源本身执行 PUT/PATCH。 如果你只想更改资源的链接(元数据)→ 对该资源关联的linkset 资源执行 PUT/PATCH。 如果你想同时更改内容和链接 → 对资源本身执行 PUT/PATCH,并包含适当的 Link 标头和 'Prefer: set-linkset'。同时设置默认关闭。

9.5 删除资源

永久移除资源及其关联元数据。

删除资源操作使用 HTTP DELETE 方法实现,如上述抽象 操作中所定义。本节指定输入、行为和响应的 HTTP 绑定。

DELETE 请求以要移除的资源或容器的 URI 为目标。客户端MAY 包含带有 ETag 的 If-Match 标头,以进行并发 检查。

删除和包含关系 删除资源时,服务器MUST 以原子方式将其从其 父容器items 列表中移除。父容器的 totalItems 计数SHOULD 相应更新,并且其 ETagMUST 被更新以反映该变更。

对于非容器资源,服务器移除资源内容、其关联元数据(linkset 资源),以及父容器中的包含关系引用。

对于容器资源,服务器默认执行非递归 删除。如果该容器非空且未请求递归,则服务器 MUST 以 409 Conflict 拒绝请求。服务器MAY 支持递归删除正在被删除的容器内的所有包含资源。 客户端MUST 使用 Depth: infinity 标头来请求 递归删除,如 [RFC4918] 中所定义。

成功时,服务器MUST 以 204 No Content 响应。服务器SHOULD 支持条件请求,如 [RFC9110] 中所定义。

如果客户端缺少授权,服务器MUST 返回 403 Forbidden(如果 客户端身份已知但权限不足)或 401 Unauthorized(如果未提供有效 身份验证)。在泄露资源存在性会造成安全风险的情况下, 服务器MAY 改为返回 404 Not Found。

示例(DELETE 非容器资源):

DELETE /alice/notes/shoppinglist.txt HTTP/1.1
Authorization: Bearer <token>
If-Match: "abc123456"

假定 ETag 匹配且客户端已获授权,服务器会以原子方式删除资源、其元数据, 并将其从父容器 /alice/notes/ 中移除:

HTTP/1.1 204 No Content

示例(DELETE 非空容器且不递归):

DELETE /alice/notes/ HTTP/1.1
Authorization: Bearer <token>

假定 /alice/notes/ 包含资源,服务器会拒绝删除:

HTTP/1.1 409 Conflict
Content-Type: text/plain

Cannot delete container /alice/notes/ - container is not empty.

示例(如果支持,递归 DELETE 容器):

DELETE /alice/notes/ HTTP/1.1
Authorization: Bearer <token>
Depth: infinity

假定服务器支持递归且客户端对所有内容都有权限,服务器会以原子方式 删除该容器及其后代:

HTTP/1.1 204 No Content

9.6 HTTP 状态 映射摘要

此表将通用 LWS 响应(来自 第 8 节)映射到 HTTP 状态码和载荷,以保持一致性,并纳入诸如 分页、并发控制、配额约束和元数据集成等特定场景:

LWS 响应 HTTP 状态码 HTTP 载荷
成功(读取或更新,返回 数据) 200 OK 响应正文中的资源 表示(用于 GET,或在 PUT/PATCH 返回内容时),以及 相关标头(Content-Type、ETag、用于元数据的 Link,例如 rel="linkset"、 rel="up")。对于容器列表,包含带有规范性上下文和成员 元数据(ID、类型、大小、时间戳)的 JSON-LD。
已创建(新资源) 201 Created 通常没有响应正文(或新资源的最小表示)。 Location 标头设置为新资源的 URI。用于并发的 ETag 等标头MUST 被包含;还包括用于服务器管理 元数据的 Link 标头。
已删除(没有内容可返回) 204 No Content 无响应正文。表示资源已被删除,或请求成功且没有 其他内容可说。服务器MAY 对永久 删除使用 410 Gone。
错误请求(输入或约束无效) 400 Bad Request 解释错误所在的错误详情。服务器SHOULD 使用 [RFC9457] 中定义的 标准格式来提供结构化错误响应,例如带有 "type"、"title"、 "status"、"detail" 和 "instance" 等字段的 JSON 对象。

10. 通知

本节定义了一种机制,使客户端能够及时接收由关联 Web 存储服务器管理的 资源发生变更时的更新。本规范定义了一种通用的 通知数据模型和订阅机制;具体的递送通道在 单独的通知套件规范中描述。

10.1 通知发现

存储可以支持通知。支持通知的存储必须 在其存储描述资源的 service 数组中通告一个 type 等于 NotificationService 的服务对象。

该服务对象必须包含一个 serviceEndpoint 属性,其 值 为订阅端点的 URI。该服务对象必须包含一个 subscriptionType 属性,其值为一个字符串数组,其中每个字符串 标识一种受支持的订阅类型。

服务对象上可以存在其他属性。

示例 10:包含通知 服务的存储描述
{
  "@context": ["https://www.w3.org/ns/lws/v1"],
  "id": "https://storage.example/",
  "type": "Storage",
  "service": [{
    "type": "NotificationService",
    "serviceEndpoint": "https://notification.example/subscriptions",
    "subscriptionType": [
      "WebhookSubscription"
    ]
  }]
}

服务器不需要支持所有订阅类型。 subscriptionType 数组会准确通告哪些类型可用。

10.2 通知数据模型

通知表示为一个类型为 Notification 的 JSON-LD 文档。信封携带有关递送 上下文的元数据,并封装一个描述该事件的 Activity Streams 2.0 [ACTIVITYSTREAMS-CORE] [ACTIVITYSTREAMS-VOCABULARY] 活动。

10.2.1 信封属性

通知信封具有以下属性:

  • type必需。其值必须 为字符串 Notification
  • storage必需。标识与 该通知关联的 LWS 存储的 URI。
  • activity必需。一个 JSON 对象或一个 JSON 对象数组, 其中每个对象均符合 Activity Streams 2.0 数据模型,并描述已发生的事件。 参见10.2.2 活动属性
示例 11:通知信封
{
  "@context": [
    "https://www.w3.org/ns/lws/v1",
    "https://www.w3.org/ns/activitystreams"
  ],
  "type": "Notification",
  "storage": "https://storage.example/",
  "activity": {
    "id": "ec4dcc48-6581-4232-81c9-584525a98693",
    "type": ["Delete"],
    "object": {
      "id": "https://storage.example/alice/notes/shopping.txt",
      "type": ["DataResource"]
    },
    "origin": "https://storage.example/alice/notes/",
    "published": "2026-03-26T10:30:00Z"
  }
}

10.2.2 活动属性

activity 属性中的每个活动对象必须符合 Activity Streams 2.0 数据模型,并且必须包含以下属性:

  • id必需。唯一标识该活动的字符串。
  • type必需。一个至少包含 一种 Activity Streams 2.0 活动类型的字符串数组。
  • object必需。一个标识该通知 所涉及资源的 JSON 对象。object 必须包含 以下 属性:
    • id必需。资源的 URI。
    • type必需。一个至少包含 一种 资源类型的字符串数组。本规范定义的值包括 ContainerDataResource。还 可以包含其他类型值。
  • published必需。一个符合 [RFC3339] 的日期时间值,指示 该活动发生的时间。

以下属性为可选

  • actor — 标识执行该操作的主体的 URI。
  • target — 标识资源被添加到的容器的 URI。 与 Create 活动一起使用。
  • origin — 标识资源从中移除的容器的 URI。 与 Delete 活动一起使用。

10.2.3 活动类型

服务器必须支持以下 Activity Streams 2.0 活动类型,以 指示 LWS 资源变更:

  • Create — 在容器中创建了一个新资源。 target 字段指示该资源被添加到的容器。
  • Update — 修改了现有资源的内容或元数据。
  • Delete — 移除了一个资源。origin 字段 指示该资源从中移除的容器。

可以支持其他活动类型。

10.2.4 批量处理通知

服务器可以通过将活动对象数组作为 activity 属性的值, 将多个活动合并到单个通知 信封中。

示例 12:批量通知
{
  "@context": [
    "https://www.w3.org/ns/lws/v1",
    "https://www.w3.org/ns/activitystreams"
  ],
  "type": "Notification",
  "storage": "https://storage.example/",
  "activity": [
    {
      "id": "a1b2c3d4-5678-9abc-def0-1234567890ab",
      "type": ["Create"],
      "object": {
        "id": "https://storage.example/alice/notes/meeting.txt",
        "type": ["DataResource"]
      },
      "target": "https://storage.example/alice/notes/",
      "published": "2026-03-26T10:30:00Z"
    },
    {
      "id": "b2c3d4e5-6789-abcd-ef01-234567890abc",
      "type": ["Update"],
      "object": {
        "id": "https://storage.example/alice/profile",
        "type": ["DataResource"]
      },
      "published": "2026-03-26T10:30:01Z"
    }
  ]
}

10.3 订阅

为接收通知,订阅者通过 向 NotificationServiceserviceEndpoint 发送 经过身份验证的 POST 请求来创建订阅。 请求正文必须符合 application/lws+json 媒体类型。

10.3.1 订阅请求

订阅请求必须包含以下字段:

  • type必需。标识订阅 类型的字符串。 其值必须NotificationServicesubscriptionType 数组中列出的类型之一。
  • topic必需。一个 URI 数组,用于标识 订阅中 包含的资源。

订阅请求可以包含具体 订阅类型所要求的其他字段。

示例 13:订阅请求
POST /subscriptions HTTP/2
Host: notification.example
Authorization: Bearer <access-token>
Content-Type: application/lws+json

{
  "@context": ["https://www.w3.org/ns/lws/v1"],
  "type": "WebhookSubscription",
  "topic": [
    "https://storage.example/alice/notes/",
    "https://storage.example/alice/profile"
  ],
  "inbox": "https://receiver.example/hooks/lws"
}

10.3.2 订阅范围

对容器的订阅是递归的:订阅者会接收 关于容器本身以及传递包含 在该容器中的所有资源的通知。对数据资源的订阅仅适用于该 单个资源。

10.3.3 订阅 授权

服务器在创建订阅必须实施资源授权。 如果订阅者不具备对 topic 数组中列出的所有 资源 等同于读取访问权限的权限,则服务器必须拒绝该 订阅 请求。

在递送通知时也必须实施授权。服务器 不得递送与某项资源有关的通知,如果在事件发生时 订阅者 无权读取该资源。这适用于订阅范围内的所有资源,包括子容器中的资源。

如果在创建订阅后,撤销了订阅者对该 订阅范围内资源或容器的访问权限,则服务器 必须停止递送受影响资源的通知。服务器 不应终止整个订阅, 除非订阅者已经失去 对 topic 数组中所有资源的访问权限。

订阅时授权用于验证订阅者具有接收通知的正当 依据。递送时授权可确保 通知始终与订阅者当前的权限一致, 并考虑创建订阅 后可能发生的授权变更。

10.3.4 订阅响应

成功创建订阅请求的响应必须符合 application/lws+json 媒体类型,并且必须包含以下 字段:

  • type必需。一个与请求中的 订阅类型相等的字符串。
  • subscription必需。表示该 订阅的 URL。

10.3.5 订阅类型 标识符

每个通知套件必须 与一个订阅类型字符串相关联。 订阅类型字符串用于 NotificationServicesubscriptionType 数组以及订阅请求的 type 字段中。

11. 访问请求与授权

访问请求和访问授权提供了一种机制,使代理能够请求访问 资源,并使存储控制器能够在已定义的约束下授予访问权限。 用于请求和授予访问权限的端点充当一种专用收件箱。

代理不会 将访问授权作为授权令牌提交给服务器。 相反,访问授权充当一份记录,说明授权了什么、授权给谁, 以及受到哪些约束。当访问授权被创建或撤销(删除)时, 服务器负责调整任何底层访问策略以反映这一 变更。访问授权端点与特定策略 执行层之间的交互不在本规范的范围内。

本节定义的访问配置文件基于 开放数字权利语言(ODRL)中的概念,包括 操作、约束和受让方。其他配置文件可以使用不同的概念框架。

11.1 发现

存储可以在其存储描述资源中通告对访问请求访问授权 的支持。当通告此类支持时,描述访问请求端点的服务 对象的 type 必须等于字符串 AccessRequestService,而描述访问授权端点的服务对象的 type 必须 等于字符串 AccessGrantService。服务 对象应当包含一个 conformsTo 属性,其值为一个 包含一个或多个 URI 的集合,用于标识该端点支持的访问配置文件。还可以包含其他属性:

示例 14:包含访问请求和授权 服务的存储描述
{
  "@context": [
    "https://www.w3.org/ns/cid/v1",
    "https://www.w3.org/ns/lws/v1"
  ],
  "id": "https://storage.example/",
  "type": "Storage",
  "service": [
    {
      "type": "StorageRoot",
      "serviceEndpoint": "https://storage.example/root/"
    },
    {
      "type": "AccessRequestService",
      "serviceEndpoint": "https://access.example/request/",
      "conformsTo": ["https://www.w3.org/ns/lws#AccessProfile"]
    },
    {
      "type": "AccessGrantService",
      "serviceEndpoint": "https://access.example/grant/",
      "conformsTo": ["https://www.w3.org/ns/lws#AccessProfile"]
    }
  ]
}

11.2 数据模型

访问请求访问授权是一个数据 对象,用于表达身份和路由属性,以及描述 所请求或获准操作的 access 对象。11.3 访问配置文件中描述了一种使用 ODRL 概念描述访问请求的配置文件。

以下示例展示了一个访问请求。该示例使用 11.4.1 JSON-LD 序列化中定义的 JSON-LD 序列化形式。

示例 15:访问请求
{
  "@context": [
    "https://www.w3.org/ns/lws/v1"
  ],
  "type": ["AccessRequest"],
  "inbox": "https://id.example/agent/inbox/",
  "storage": "https://storage.example/",
  "access": [{
    "type": ["AccessPolicy"],
    "action": ["read", "create"],
    "assignee": "https://id.example/agent",
    "target": {
      "type": "StorageResource",
      "value": ["https://storage.example/root/projects/"]
    },
    "constraint": [
      {
        "leftOperand": "purpose",
        "operator": "eq",
        "rightOperand": "https://purpose.example/collaboration"
      },
      {
        "leftOperand": "dateTime",
        "operator": "lteq",
        "rightOperand": "2026-06-09T10:00:00Z"
      }
    ]
  }]
}

以下示例展示了一个访问授权。该示例使用 11.4.1 JSON-LD 序列化中定义的 JSON-LD 序列化形式。

示例 16:访问授权
{
  "@context": [
    "https://www.w3.org/ns/lws/v1"
  ],
  "type": ["AccessGrant"],
  "storage": "https://storage.example/",
  "access": [{
    "type": ["AccessPolicy"],
    "action": ["read"],
    "assignee": "https://id.example/agent",
    "target": {
      "type": "StorageResource",
      "value": ["https://storage.example/root/projects/"]
    },
    "constraint": [
      {
        "leftOperand": "purpose",
        "operator": "eq",
        "rightOperand": "https://purpose.example/collaboration"
      },
      {
        "leftOperand": "dateTime",
        "operator": "lteq",
        "rightOperand": "2026-06-09T10:00:00Z"
      }
    ]
  }]
}

访问请求访问授权可以存在其他属性。

11.2.1 类型

type 属性表示文档的类型。

type 属性的值必须是一个或多个 术语绝对 URL 字符串。对于 访问请求,该值必须 包含术语 AccessRequest。 对于访问授权,该值必须 包含术语 AccessGrant。还可以包含其他类型值。

此属性为必需

本文档为访问请求访问授权定义以下类型值:

  • AccessRequest主体提出的资源访问请求。
  • AccessGrant存储 控制者授予 资源访问权限的授权。
示例 17:type 属性
{
  "type": ["AccessGrant"]
}

11.2.2 存储

storage 属性标识访问请求访问授权所适用的 LWS 存储。

storage 属性的值必须是 URI。

此属性为必需

示例 18:storage 属性
{
  "storage": "https://storage.example/"
}

11.2.3 收件箱

inbox 属性指定一个 URI,用于接收与 访问请求访问授权 相关的通知(参见11.6 通知)。

inbox 属性的值必须是 URI。

此属性为可选

示例 19:inbox 属性
{
  "inbox": "https://id.example/agent/inbox/"
}

11.2.4 访问

access 属性根据服务器支持的配置文件,描述一个或多个 访问配置文件的特征。基于 ODRL 信息模型的 配置文件在11.3 访问配置文件中描述。

access 属性的值必须是包含一个 或多个对象的集合。

此属性为必需

11.3 访问配置文件

本规范定义了一个基于 ODRL 信息模型ODRL 词汇表的访问配置文件,该配置文件 由以下 URL 标识: https://www.w3.org/ns/lws#AccessProfile

11.3.1 类型

type 属性表示访问策略的类型。

type 属性的值必须是一个或多个 术语绝对 URL 字符串,并且必须包含 术语 AccessPolicy。还可以包含其他类型值。

此属性为必需

示例 20:访问策略类型
{
  "access": [{
    "type": ["AccessPolicy"]
  }]
}

11.3.2 操作

action 属性描述操作,即主体希望 执行的操作(对于请求),或获准执行的操作(对于授权)。

action 属性的值必须是包含一个 或多个字符串的集合。每个值必须对应服务器能够识别的操作。 必须支持以下值:readmodifycreatedeletereadmodifydelete 值由 ODRL 词汇表定义。 create 值由本 规范定义。

这些操作值与 LWS 操作的对应关系如下:

  • read — 获取资源或其元数据(HTTP GET、HEAD)
  • modify — 修改现有资源(HTTP PUT、PATCH)
  • create — 在容器中创建新资源(HTTP POST)
  • delete — 移除现有资源(HTTP DELETE)

此属性为必需

示例 21:action 属性
{
  "access": [{
    "action": ["read", "create"]
  }]
}

11.3.3 受让方

assignee 属性标识请求访问的一方(对于 请求),或被授予访问权限的一方(对于授权)。

assignee 属性的值必须是 URI。公共 访问权限可以使用FOAF 词汇表中的 Agent 类进行 分配,该类由 URI http://xmlns.com/foaf/0.1/Agent 标识。

此属性为必需

示例 22:assignee 属性
{
  "access": [{
    "assignee": "https://id.example/agent"
  }]
}

11.3.4 目标

target 属性标识 访问请求访问授权 所适用的资源。

target 属性必须是一个包含以下 属性的对象:

  • type — 用于标识目标匹配器 类型的术语绝对 URL 字符串
  • value — 用于标识 目标资源的一个或多个字符串的集合。

本规范定义以下可用于 目标对象的 type 值:

  • https://www.w3.org/ns/lws#DataResource — 匹配 类型为 lws:DataResource 的资源。
  • https://www.w3.org/ns/lws#Container — 匹配 类型为 lws:Container 的资源。
  • https://www.w3.org/ns/lws#StorageResource — 匹配 由存储管理的任何资源。

服务器可以支持其他类型值。

此属性为可选

示例 23:包含资源类型的 target 属性
{
  "access": [{
    "target": {
      "type": "StorageResource",
      "value": [
        "https://storage.example/root/2025",
        "https://storage.example/root/2026"
      ]
    }
  }]
}

11.3.5 约束

constraint 属性定义限制或限定所请求或授予 访问权限的条件。此属性使用 ODRL 约束模型。

constraint 属性的值(如果存在)必须是一个 约束对象集合。每个约束对象必须包含以下 属性:

  • leftOperand — 标识受约束操作数的字符串。
  • operator — 标识比较运算符的字符串。
  • rightOperand — 用于比较的值。其类型取决于 leftOperand

当存在多个约束对象时,所有约束对象都必须 得到满足。

通告支持此配置文件的服务器必须支持以下 leftOperand 值:

  • client — 表示 HTTP 请求的客户端标识符
  • format — 表示目标 HTTP 资源的媒体类型
  • type — 表示资源链接 标头中表达的类型 URL
  • purpose — 表示所请求或授予 访问权限的预期用途
  • dateTime — 表示当前日期和时间

此属性为可选

以下示例说明了这些约束的用法:

11.3.5.1 用途约束

以下示例使用值为 purposeleftOperand 来描述所请求或授予 访问权限的预期用途。使用 eq 运算符时, rightOperand 的值是标识用途的 URI。 使用 isAnyOf 运算符时,rightOperand 的值是一个用途 URI 数组,如果所声明的用途 与列出的任意值匹配,则满足该约束:

示例 24:用途约束
{
  "access": [{
    "constraint": [
      {
        "leftOperand": "purpose",
        "operator": "isAnyOf",
        "rightOperand": [
          "https://purpose.example/collaboration",
          "https://purpose.example/research"
        ]
      }
    ]
  }]
}
11.3.5.2 客户端约束

以下示例使用值为 clientleftOperand,将访问权限限制 为特定客户端应用程序。使用 eq 运算符时, rightOperand 的值是标识客户端的 URI:

示例 25:客户端约束
{
  "access": [{
    "constraint": [
      {
        "leftOperand": "client",
        "operator": "eq",
        "rightOperand": "https://app.example/client-id"
      }
    ]
  }]
}
11.3.5.3 格式约束

以下示例使用值为 formatleftOperand,将 访问权限限制为具有特定媒体类型的资源。当使用 eq 运算符 时,rightOperand 值是标识 IANA 媒体类型的字符串。当 使用 isAnyOf 运算符时,rightOperand 值 是一个媒体类型字符串数组;如果资源的 媒体类型与列出的任意值匹配,则允许访问:

示例 26:格式约束
{
  "access": [{
    "constraint": [
      {
        "leftOperand": "format",
        "operator": "isAnyOf",
        "rightOperand": ["image/jpeg", "image/png"]
      }
    ]
  }]
}
11.3.5.4 资源类型 约束

所有 LWS 资源都将包含指示类型值的链接标头:

以下示例使用值为 typeleftOperand,根据 HTTP Link 标头中通告的资源类型限制访问权限。 使用 eq 运算符时,rightOperand 的值 是标识资源类型的 URI。使用 isAnyOf 运算符时, rightOperand 的值是一个类型 URI 数组,如果资源的 类型与列出的任意值匹配,则允许访问:

示例 28:资源类型约束
{
  "access": [{
    "constraint": [
      {
        "leftOperand": "type",
        "operator": "isAnyOf",
        "rightOperand": [
          "https://type.example/Playlist",
          "https://type.example/Song"
        ]
      }
    ]
  }]
}
11.3.5.5 时间约束

以下示例使用值为 dateTimeleftOperand,将访问权限限制 在特定时间窗口内。gteq 运算符定义 窗口的开始,lteq 运算符定义窗口的结束。 时间约束的 rightOperand 值是 XML Schema dateTime 字符串:

示例 29:时间约束
{
  "access": [{
    "constraint": [
      {
        "leftOperand": "dateTime",
        "operator": "gteq",
        "rightOperand": "2026-03-09T12:00:00Z"
      },
      {
        "leftOperand": "dateTime",
        "operator": "lteq",
        "rightOperand": "2026-06-09T10:00:00Z"
      }
    ]
  }]
}
11.3.5.6 组合约束

当存在多个约束对象时,所有约束对象都必须 得到满足,才能 允许访问。以下示例将访问权限限制为特定日期之前的特定客户端 应用程序:

示例 30:组合约束
{
  "access": [{
    "action": ["read"],
    "assignee": "https://id.example/agent",
    "target": {
      "type": "StorageResource",
      "value": ["https://storage.example/root/projects/"]
    },
    "constraint": [
      {
        "leftOperand": "dateTime",
        "operator": "lteq",
        "rightOperand": "2026-06-09T10:00:00Z"
      },
      {
        "leftOperand": "client",
        "operator": "eq",
        "rightOperand": "https://app.example/client-id"
      }
    ]
  }]
}

11.4 序列化

本节定义的数据模型独立于任何特定的 序列化形式。

11.4.1 JSON-LD 序列化

本规范为访问请求访问授权定义了一种 JSON-LD 序列化形式。使用此序列化形式的文档必须包含一个 @context 属性,其值是一个包含 https://www.w3.org/ns/lws/v1 的有序集合。还可以 包含其他上下文条目,以定义扩展术语。

与此序列化形式关联的媒体类型为 application/lws+json

示例 31:JSON-LD @context
{
  "@context": [
    "https://www.w3.org/ns/lws/v1"
  ]
}

11.5 协议

访问请求访问授权端点 是 LWS 容器,并且必须 符合本规范定义的规则。

这些端点至少需要支持 GET 和 POST 操作。建议支持 DELETE 操作。 还可以支持其他操作。

这些端点对请求和响应有效载荷都必须支持 11.4.1 JSON-LD 序列化中定义的 JSON-LD 序列化形式。服务器 可以支持其他序列化形式。

主体通过向 访问请求端点提交 POST 请求来 创建访问请求存储 控制者通过 向访问授权端点提交 POST 请求来创建访问授权

成功的 POST 操作必须使用 Location 标头作出响应, 该标头被设置为 新资源的 URL。

11.5.1 访问请求端点

  • POST / — 创建访问请求。
  • GET / — 获取访问请求列表。
  • GET /:id — 获取特定访问请求。
  • DELETE /:id — 取消访问请求。

11.5.2 访问授权端点

  • POST / — 创建访问授权。
  • GET / — 获取访问授权列表。
  • GET /:id — 获取特定访问授权。
  • DELETE /:id — 撤销访问授权。

11.6 通知

问题 103:LWS 通知功能 工作项

本节需要与 LWS 尚未定义的通知章节保持一致。

通知提供了一种机制,用于告知主体存储 控制者有关 访问请求访问授权的变更。当 访问请求访问授权上存在 inbox 属性时,服务器应当向该端点递送 通知,将事件告知 受让方。

通知的序列化形式必须符合 LWS 通知数据模型的要求。

递送到 inbox 端点的通知必须符合 LWS 协议中为通知递送定义的要求。

本节描述的通知机制类似于 关联数据通知模式,其中 通过 inbox 属性发现通知端点,并通过向该收件箱发送 POST 请求来递送通知。

11.6.1 通知事件

服务器应当响应以下事件发送通知:

服务器可以响应其他事件发送通知。

12. LWS 媒体类型

12.1 LWS 媒体类型

LWS 存储描述必须可使用媒体类型 application/lws+cid 进行序列化。 application/lws+cid 媒体类型标识一种文档,该文档是 W3C 受控标识符文档 [CID-1.0] 的一种特化,并使用 LWS 词汇表进行了扩展。

LWS 容器表示必须支持媒体类型 application/lws+json

虽然 LWS 容器表示使用 JSON-LD 约定,但 LWS 的约束和要求 使使用特定媒体类型具有合理性。由于 LWS 容器可以被视为 JSON-LD 的受限配置文件, 实现应当application/ld+json; profile="https://www.w3.org/ns/lws/v1" 媒体类型视为等同于 application/lws+json

12.1.1 媒体类型等价性

对于容器表示,媒体类型 application/lws+jsonapplication/ld+jsonapplication/json 是等价的:响应主体是同一个 JSON-LD 文档, 符合容器表示结构,该结构定义于8.1 容器 表示中,只有 Content-Type 响应标头不同。服务器必须满足对其中任一媒体类型的请求,并且必须Content-Type 响应标头设置为所请求的 媒体类型。

由于容器响应的 Content-Type 取决于请求的 Accept 标头,因此这些响应应当包含 Vary: Accept 标头 [RFC9110]。

注(非规范性):此等价性仅适用于上述三种媒体类型。 与任何 HTTP 资源一样,服务器可以通过标准内容协商 [RFC9110] 提供容器的其他表示(例如 text/turtle);本规范既不要求也不排除此类支持。

12.1.2 分页

某些复合资源(例如容器)可能包含大量资源。 为了允许客户端增量检索列表,服务器应当为成员数量超过服务器所确定 阈值的容器支持 分页。

12.1.2.1 分页模型

分页基于链接:服务器通过 HTTP Link 标头提供分页 URI [RFC8288], 使客户端无需依赖数字偏移量即可遍历完整列表。

当列表分页时,响应主体仅包含当前页面中的项目。复合 资源的 idtypetotalItems 属性 反映完整的成员集合,而 items 仅包含当前页面中的资源。

12.1.2.3 请求页面

客户端请求复合资源的 URI 以获取第一页。响应包含 分页 Link 标头,客户端跟随这些标头来检索后续页面。服务器也可以支持 通过先前扫描期间获得的分页 URI 直接访问特定页面。

返回分页响应时,服务器必须以 200 OK 响应。响应主体中的 totalItems 属性应当反映所有页面中的项目总数, 而不只是当前页面中的项目数。

12.1.2.4 示例: 分页容器

请求:

GET /alice/photos/ HTTP/1.1
Authorization: Bearer <token>
Accept: application/lws+json

响应(第一页):

HTTP/1.1 200 OK
Content-Type: application/lws+json
ETag: "photos-page1-etag"
Link: </alice/photos/.meta>; rel="linkset"; type="application/linkset+json"
Link: </alice/>; rel="up"
Link: <https://www.w3.org/ns/lws#Container>; rel="type"
Link: </alice/photos/?page=1>; rel="first"
Link: </alice/photos/?page=3>; rel="last"
Link: </alice/photos/?page=2>; rel="next"

{
  "@context": "https://www.w3.org/ns/lws/v1",
  "id": "/alice/photos/",
  "type": "Container",
  "totalItems": 150,
  "items": [
    {
      "type": "DataResource",
      "id": "/alice/photos/vacation.jpg",
      "format": "image/jpeg",
      "size": 248392,
      "modified": "2025-11-20T10:30:00Z"
    },
    {
      "type": "DataResource",
      "id": "/alice/photos/portrait.png",
      "format": "image/png",
      "size": 102400,
      "modified": "2025-11-21T14:15:00Z"
    }
  ]
}

请求(下一页):

GET /alice/photos/?page=2 HTTP/1.1
Authorization: Bearer <token>
Accept: application/lws+json

响应(中间页):

HTTP/1.1 200 OK
Content-Type: application/lws+json
ETag: "photos-page2-etag"
Link: </alice/photos/.meta>; rel="linkset"; type="application/linkset+json"
Link: </alice/>; rel="up"
Link: <https://www.w3.org/ns/lws#Container>; rel="type"
Link: </alice/photos/?page=1>; rel="first"
Link: </alice/photos/?page=1>; rel="prev"
Link: </alice/photos/?page=3>; rel="next"
Link: </alice/photos/?page=3>; rel="last"

{
  "@context": "https://www.w3.org/ns/lws/v1",
  "id": "/alice/photos/",
  "type": "Container",
  "totalItems": 150,
  "items": [
    {
      "type": "DataResource",
      "id": "/alice/photos/sunset.jpg",
      "format": "image/jpeg",
      "size": 315000,
      "modified": "2025-11-22T09:00:00Z"
    }
  ]
}

13. JSON-LD 上下文

LWS JSON-LD 上下文由 URL https://www.w3.org/ns/lws/v1 标识。 从该 URL 解析得到的文档的 SHA2-256 摘要包含在下表中:

上下文 URL 和哈希值
URL: https://www.w3.org/ns/lws/v1
SHA2-256 摘要: 待办:在上下文文档最终确定后加入 JSON-LD 上下文摘要

可以使用如下命令验证摘要: curl -sL -H "Accept: application/ld+json" https://www.w3.org/ns/lws/v1 | openssl dgst -sha256

建议生产系统不要在运行时获取远程 JSON-LD 上下文文档。 在本地捆绑或缓存上下文可以消除对外部基础设施的运行时依赖, 减少延迟,并防止上下文操纵攻击。

14. 资源标识

定义如何在 LWS 协议中标识和寻址资源,包括 URI 方案、资源命名约定和解析机制。本节可能会移至 另一节中;例如“资源访问”

此处有意留空

15. 可移植性注意事项

描述确保 LWS 实现能够跨不同 平台、环境和存储后端工作,同时保持互操作性的注意事项,并提供 支持更换存储提供商的操作能力

此处有意留空

16. 安全注意事项

本节为非规范性内容。

正式的安全注意事项章节,涵盖威胁模型、安全要求和 安全部署 LWS 的实现指南。

OAuth 2.0 安全当前最佳实践 [RFC9700] 中描述的建议适用于本 规范。

16.1 传输安全

本节为非规范性内容。

传输层安全性(TLS)是防止篡改、欺骗和 信息泄露的重要机制。受 TLS 保护的通信可按照 [RFC6125] 进行验证。 实现安全注意事项可参见“安全使用传输 层安全性(TLS)和数据报传输层安全性(DTLS)的建议”[RFC9325]。

16.2 令牌安全

本节为非规范性内容。

持有者令牌和数字凭证容易被窃取和重放。缓解措施包括使用 合理的较短生命周期、将令牌绑定到特定受众以及安全存储令牌。

16.3 访问请求与授权

本节为非规范性内容。

16.4 通知

本节为非规范性内容。

17. 隐私注意事项

本节为非规范性内容。

LWS 协议的隐私影响,包括数据最小化、用户同意和 隐私保护型实现模式。

凭证携带有关用户和主体的信息。虽然数字签名可以防止篡改, 但客户端或第三方仍有可能读取未加密凭证中的值。

因此,建议凭证颁发者创建仅包含身份验证或授权所必需信息的令牌, 并避免包含敏感属性,除非确有需要。

一般而言,将未加密的凭证数据写入日志是一种反模式。在确有必要的情况下, 实现可以截断凭证或对其进行哈希处理,以保护凭证主体的隐私。

在 JWT 中使用假名标识符时,存储服务器仍可能随时间推移关联来自同一 主体 的请求。 为在这种情况下保护用户隐私,客户端应用程序可以请求批量颁发 JWT,其中每个 JWT 仅使用一次。 这并不能阻止存储服务器使用 JWT 内容的相似性或来源 IP 地址等其他信息 来关联请求。使用假名标识符时,授权服务器需要注意 不要多次颁发相同的标识符。

17.1 访问请求与授权

本节为非规范性内容。

17.2 通知

本节为非规范性内容。

18. IANA 注意事项

本节为非规范性内容。

18.1 well-known URI 注册表

本规范向 RFC 5785 [RFC5785] 建立的“Well-Known URI”注册表 中添加以下值。

18.2 OAuth 授权服务器元数据注册表

本规范向 [RFC8414] 建立的“OAuth 授权服务器元数据”注册表 中添加以下值。

18.3 application/lws+json 媒体类型

本规范专门注册 application/lws+json 媒体类型,用于 标识符合关联 Web 存储容器格式的文档。

请注意,虽然关联 Web 存储格式使用 JSON-LD 约定,但 LWS 实现还存在许多 约束和附加 要求,足以说明使用特定媒体类型的合理性。

由于 LWS 容器可视为 JSON-LD 的受限配置文件,实现应当application/ld+json; profile="https://www.w3.org/ns/lws/v1" 媒体类型视为等同于 application/lws+json

18.4 application/lws+cid 媒体类型

本规范注册 application/lws+cid 媒体类型,用于标识 符合关联 Web 存储协议的存储描述文档,作为 W3C 受控标识符 1.0 文档格式的一种特化形式。

A. 致谢

本节为非规范性内容。

本规范大量借鉴了 Solid Protocol [Solid-Protocol],该协议由 Sarven Capadisli、Tim Berners-Lee、Kjetil Kjernsmo、Ruben Verborgh、Justin Bingham、Dmitri Zagidulin 随时间推移编辑而成。

B. 参考文献

B.1 规范性参考文献

[ACTIVITYSTREAMS-CORE]
活动流 2.0。James Snell;Evan Prodromou。W3C。2017 年 5 月 23 日。W3C 推荐标准。URL:https://www.w3.org/TR/activitystreams-core/
[ACTIVITYSTREAMS-VOCABULARY]
活动词汇表。 James Snell;Evan Prodromou。W3C。2017 年 5 月 23 日。W3C 推荐标准。URL:https://www.w3.org/TR/activitystreams-vocabulary/
[CID-1.0]
受控标识符 v1.0。Michael Jones;Manu Sporny。W3C。2025 年 5 月 15 日。W3C 推荐标准。网址:https://www.w3.org/TR/cid-1.0/
[FOAF]
FOAF 词汇表规范 0.99(帕丁顿 版)。Dan Brickley;Libby Miller。FOAF 项目。2014 年 1 月 14 日。URL:http://xmlns.com/foaf/spec/
[JSON-LD11]
JSON-LD 1.1。Gregg Kellogg; Pierre-Antoine Champin;Dave Longley。W3C。2020 年 7 月 16 日。W3C 推荐标准。URL:https://www.w3.org/TR/json-ld11/
[ODRL-MODEL]
ODRL 信息模型 2.2。Renato Iannella;Serena Villata。W3C。2018 年 2 月 15 日。W3C 推荐标准。URL:https://www.w3.org/TR/odrl-model/
[ODRL-VOCAB]
ODRL 词汇表与表达式 2.2。 Renato Iannella;Michael Steidl;Stuart Myles;Víctor Rodríguez-Doncel。W3C。2018 年 2 月 15 日。W3C 推荐标准。URL:https://www.w3.org/TR/odrl-vocab/
[OPENID-CONNECT-CORE]
OpenID Connect Core 1.0 (包含勘误集 2)。N. Sakimura;J. Bradley;M. Jones;B. de Medeiros;C. Mortimore。OpenID Foundation。2023 年 12 月 15 日。最终版。URL:https://openid.net/specs/openid-connect-core-1_0.html
[RFC2119]
用于在 RFC 中指示 要求级别的关键词。S. Bradner。IETF。1997 年 3 月。当前最佳实践。URL:https://www.rfc-editor.org/info/rfc2119/
[RFC3339]
互联网上的日期和时间: 时间戳。G. Klyne;C. Newman。IETF。2002 年 7 月。提议标准。URL:https://www.rfc-editor.org/info/rfc3339/
[RFC3986]
统一资源标识符(URI):通用 语法。T. Berners-Lee;R. Fielding;L. Masinter。IETF。2005 年 1 月。互联网 标准。URL:https://www.rfc-editor.org/info/rfc3986/
[RFC4918]
用于 Web 分布式 创作与版本控制(WebDAV)的 HTTP 扩展。L. Dusseault,编辑。IETF。2007 年 6 月。提议 标准。URL:https://www.rfc-editor.org/info/rfc4918/
[RFC5789]
HTTP 的 PATCH 方法。L. Dusseault;J. Snell。IETF。2010 年 3 月。提议标准。URL:https://httpwg.org/specs/rfc5789.html
[RFC6585]
其他 HTTP 状态码。M. Nottingham;R. Fielding。IETF。2012 年 4 月。提议标准。URL:https://httpwg.org/specs/rfc6585.html
[RFC6749]
OAuth 2.0 授权 框架。D. Hardt,编辑。IETF。2012 年 10 月。提议标准。URL:https://www.rfc-editor.org/info/rfc6749/
[RFC6750]
OAuth 2.0 授权框架: 持有者令牌用法。M. Jones;D. Hardt。IETF。2012 年 10 月。提议标准。 URL:https://www.rfc-editor.org/info/rfc6750/
[RFC7231]
超文本传输协议(HTTP/1.1): 语义和内容。R. Fielding,编辑;J. Reschke,编辑。IETF。2014 年 6 月。 提议标准。URL:https://httpwg.org/specs/rfc7231.html
[RFC7232]
超文本传输协议(HTTP/1.1): 条件请求。R. Fielding,编辑;J. Reschke,编辑。IETF。2014 年 6 月。提议 标准。URL:https://httpwg.org/specs/rfc7232.html
[RFC7233]
超文本传输协议(HTTP/1.1):范围 请求。R. Fielding,编辑;Y. Lafon,编辑;J. Reschke,编辑。IETF。2014 年 6 月。 提议标准。URL:https://httpwg.org/specs/rfc7233.html
[RFC7240]
HTTP 的 Prefer 标头。J. Snell。IETF。2014 年 6 月。提议标准。URL:https://www.rfc-editor.org/info/rfc7240/
[RFC7386]
JSON 合并补丁。P. Hoffman;J. Snell。IETF。2014 年 10 月。提议标准。URL:https://www.rfc-editor.org/info/rfc7386/
[RFC8174]
RFC 2119 关键词中大写与小写的歧义。B. Leiba。IETF。2017 年 5 月。当前最佳实践。URL:https://www.rfc-editor.org/info/rfc8174/
[RFC8288]
Web 链接。M. Nottingham。IETF。 2017 年 10 月。提议标准。URL:https://httpwg.org/specs/rfc8288.html
[RFC8414]
OAuth 2.0 授权服务器 元数据。M. Jones;N. Sakimura;J. Bradley。IETF。2018 年 6 月。提议标准。 URL:https://www.rfc-editor.org/info/rfc8414/
[RFC8693]
OAuth 2.0 令牌交换。M. Jones;A. Nadalin;B. Campbell,编辑;J. Bradley;C. Mortimore。IETF。2020 年 1 月。提议 标准。URL:https://www.rfc-editor.org/info/rfc8693/
[RFC9068]
OAuth 2.0 访问令牌的 JSON Web Token(JWT)配置文件。V. Bertocci。IETF。2021 年 10 月。提议标准。URL:https://www.rfc-editor.org/info/rfc9068/
[RFC9110]
HTTP 语义。R. Fielding,编辑; M. Nottingham,编辑;J. Reschke,编辑。IETF。2022 年 6 月。互联网标准。URL:https://httpwg.org/specs/rfc9110.html
[rfc9112]
HTTP/1.1。R. Fielding,编辑;M. Nottingham,编辑;J. Reschke,编辑。IETF。2022 年 6 月。互联网标准。URL:https://httpwg.org/specs/rfc9112.html
[RFC9264]
链接集:链接集的媒体类型和链接关系 类型。E. Wilde;H. Van de Sompel。IETF。2022 年 7 月。提议 标准。URL:https://www.rfc-editor.org/info/rfc9264/
[RFC9457]
HTTP API 的问题详情。 M. Nottingham;E. Wilde;S. Dalal。IETF。2023 年 7 月。提议标准。URL:https://www.rfc-editor.org/info/rfc9457/
[URL]
URL 标准。Anne van Kesteren。WHATWG。 现行标准。URL:https://url.spec.whatwg.org/
[WebArch]
万维网架构,第一 卷。Ian Jacobs;Norman Walsh。W3C。2004 年 12 月 15 日。W3C 推荐标准。URL:https://www.w3.org/TR/webarch/
[XMLSCHEMA11-2]
W3C XML 模式定义语言(XSD)1.1 第 2 部分:数据类型。David Peterson;Sandy Gao;Ashok Malhotra;Michael Sperberg-McQueen;Henry Thompson;Paul V. Biron 等。W3C。2012 年 4 月 5 日。W3C 推荐标准。URL: https://www.w3.org/TR/xmlschema11-2/

B.2 资料性参考文献

[LDN]
关联数据通知。Sarven Capadisli; Amy Guy。W3C。2017 年 5 月 2 日。W3C 推荐标准。URL:https://www.w3.org/TR/ldn/
[RFC5785]
定义众所周知的统一资源 标识符(URI)。M. Nottingham;E. Hammer-Lahav。IETF。2010 年 4 月。提议 标准。URL:https://www.rfc-editor.org/info/rfc5785/
[RFC6125]
在传输层安全性(TLS)上下文中使用 X.509(PKIX)证书表示和验证互联网公钥基础设施内 基于域的应用服务身份。P. Saint-Andre;J. Hodges。IETF。2011 年 3 月。提议标准。URL:https://www.rfc-editor.org/info/rfc6125/
[RFC8259]
JavaScript 对象表示法(JSON)数据 交换格式。T. Bray,编辑。IETF。2017 年 12 月。互联网标准。URL:https://www.rfc-editor.org/info/rfc8259/
[RFC9325]
安全使用传输 层安全性(TLS)和数据报传输层安全性(DTLS)的建议。Y. Sheffer;P. Saint-Andre;T. Fossati。IETF。2022 年 11 月。当前最佳实践。URL:https://www.rfc-editor.org/info/rfc9325/
[RFC9700]
OAuth 2.0 安全当前最佳实践。T. Lodderstedt;J. Bradley;A. Labunets;D. Fett。IETF。2025 年 1 月。 当前最佳实践。URL:https://www.rfc-editor.org/info/rfc9700/
[Solid-Protocol]
Solid 协议。Sarven Capadisli; Tim Berners-Lee;Kjetil Kjernsmo。Solid 社区组。2024 年 5 月 12 日。社区组报告草案。 URL:https://solidproject.org/TR/protocol