﻿# C端权限与访问控制规则

版本：v0.7
状态：第一阶段 MVP 范围已确认；访问分支原型已覆盖，待联调与开发
适用表面：VISTA C

## 修订记录

| 日期 | 版本 | 变更类型 | 变更摘要 |
| --- | --- | --- | --- |
| 2026-07-29 | v0.1 | 初始创建 / 重大范围确认 | 将 C 端权限和顾客登录验证纳入 MVP；定义公开访问与受限访问两种模式、A/B/C 三端责任、登录后页面级授权校验、会话失效处理及 403/404 触发边界。 |
| 2026-07-29 | v0.2 | 重大：登录判断与顾客记录定稿 | 明确指定顾客链接、免密码链接、邮箱加密码三种登录判断；登录成功后在当前浏览器保存最少的顾客识别信息，供后续数据上报关联顾客。 |
| 2026-07-29 | v0.3 | 重大：免密码设置归属定稿 | 确认免密码在“用户分享设置”中按顾客单独设定，并对该顾客所有分享页面统一生效；页面和单条分享链接不分别设置。 |
| 2026-07-29 | v0.4 | 重大：B端流程边界定稿 | 分享验证由现有 B 端产生；MVP 不修改 B 端业务流程、设置页面或分享生成方式，C 端只读取已有结果并完成登录与页面访问判断。 |
| 2026-07-29 | v0.4 | 非重大：原型交付同步 | 响应式原型已覆盖三种登录分支、登录后回到原目标、403 切换顾客和 404 结果；真实权限判断仍待接口联调。 |
| 2026-07-29 | v0.5 | 重大：导航权限可见性进入 MVP | 页面导航进入 MVP；导航只展示同一集合内当前匿名身份或已登录顾客实际可访问的页面，无权限页面不显示禁用项或摘要。 |
| 2026-08-03 | v0.6 | 引用迁移 | 顾客登录与页面导航组件引用迁移到合并后的当前组件需求目录；权限规则不变。 |
| 2026-08-03 | v0.7 | 重大：顾客认证与会话规则更新 | 以 B端提供的顾客分享验证码规则取代旧密码分支；确认同项目会话复用、逐页静默授权、绝对禁止跨项目复用和退出登录。 |

## 1. 文档目的与适用对象

本文档定义第一阶段 MVP 中，顾客通过独立页面链接访问项目概览页、周边地图页和户型列表页时，C 端如何判断是否需要登录、是否具有页面权限，以及失败后进入登录组件、403 或 404 的规则。

适用对象：产品、A/B/C 端开发、测试、安全评审及 Codex。

关联文档：

- [`03-通用组件体系/13-顾客登录组件PRD.md`](03-通用组件体系/13-顾客登录组件PRD.md)
- [`06-系统状态与错误页规则.md`](06-系统状态与错误页规则.md)
- [`01-页面体系/00-页面开发清单.md`](01-页面体系/00-页面开发清单.md)
- [`03-通用组件体系/02-页面导航组件PRD.md`](03-通用组件体系/02-页面导航组件PRD.md)

## 2. MVP 结论

MVP 支持两种页面访问模式：

| 访问模式 | 页面发布快照 | C 端行为 |
| --- | --- | --- |
| 公开访问 | `anonymous_access = true` | 页面存在且已发布时，匿名顾客直接访问；不调用登录组件，不要求 B 端顾客授权。 |
| 顾客登录后访问 | `anonymous_access = false` | 先按访问链接完成顾客登录，再检查该顾客能否访问当前页面；通过后展示页面。 |

核心判断：

- **未登录或登录失效**：调用顾客登录组件，不进入错误页。
- **登录成功且有页面授权**：进入原目标页面。
- **登录成功但无页面授权**：进入 403。
- **项目或页面不存在、未发布、已下线或链接无效**：进入 404。

顾客登录先回答“当前顾客是谁”，页面权限再回答“该顾客能否访问当前页面”。两步必须分开。

> v0.7 优先规则：受限页的验证码规则和验证结果由 B端提供，C端不再固化密码、免密码或输入字段分支。验证码验证成功不等于当前页面已获授权，仍须取得 B端对当前页面的明确允许。

受限页面的输入项、验证码格式、发送方式、失败次数限制和验证方式由 B端顾客分享规则决定。C端只按 B端提供的规则呈现输入和反馈，不能将旧的邮箱、密码或免密码分支写死为产品规则。

## 3. 三端责任边界

| 责任端 | MVP 职责 | 明确不承担 |
| --- | --- | --- |
| A 端 | 在项目页面发布设置中保存是否允许未登录顾客查看；页面下线与重新发布。 | 不选择具体顾客，不创建顾客账号，不配置登录字段和登录保持规则。 |
| 现有 B 端 | 提供顾客分享验证规则、验证结果、正式分享链接和当前页面访问结果。 | C端不定义验证码具体规则，也不自行授予访问权限。 |
| C 端 | 读取 B 端已有结果，识别目标页面和访问链接，完成顾客登录，在浏览器保存顾客记录，检查页面权限，并进入页面或 403/404。 | 不自行授予权限，不因登录成功扩大访问范围，不在 Widget 内判断页面权限。 |

Widget 和通用业务组件仅在页面访问校验通过后工作。M-01、M-20、M-10、项目 Logo、项目联系和图片查看器不分别实现一套顾客权限。页面导航只消费已经按当前身份过滤后的页面清单，不自行授予权限。

## 4. 权限对象与最小输入

| 输入 | 来源 | 作用 | 约束 |
| --- | --- | --- | --- |
| `instance_id` | 页面访问链接 / 路由解析 | 确定本次访问的具体项目页面 | 必须指向真实存在的页面实例；模板标识不能替代。 |
| 页面发布状态 | A 端发布结果 | 判断页面是否已发布、已下线 | 未发布或下线进入 404。 |
| `anonymous_access` | 当前线上发布快照 | 决定是否需要顾客登录 | 编辑中但未重新发布的值不得立即影响线上。 |
| 顾客分享验证规则与结果 | B 端生成的正式分享链接及验证服务 | 决定 C端需要呈现的输入、验证反馈和认证成功结果 | 不在 C端固化字段、验证码或免验证分支；不可用时按验证失败安全处理。 |
| 顾客登录状态 | C 端登录功能 | 确定当前顾客是否已经完成登录 | 过期、无效或被撤销时重新登录。 |
| 顾客识别编号 | 登录成功结果 | 检查当前顾客能否访问页面，并供后续数据上报关联顾客 | 不用邮箱代替；不在页面、访问链接或可见日志中展示。 |
| 页面授权结果 | B 端权限服务 | 判断当前顾客是否可访问当前 `instance_id` | 只接受明确允许；缺失、未知或失败不得按允许处理。 |

MVP 不定义页面有效期或单次访问链接的有效期。页面保持有效直至 A 端下线；顾客登录保持多久由开发方案确定。

## 5. 访问状态机

```mermaid
flowchart TD
    A["顾客打开独立页面链接"] --> B{"页面存在且已发布？"}
    B -- "否" --> E404["404"]
    B -- "是" --> C{"允许未登录访问？"}
    C -- "是" --> PAGE["进入目标页面"]
    C -- "否" --> D{"顾客登录有效？"}
    D -- "否" --> LOGIN["按访问链接完成顾客登录"]
    LOGIN --> LOK{"登录成功？"}
    LOK -- "否" --> LOGIN
    LOK -- "是" --> AUTH{"顾客拥有当前页面授权？"}
    D -- "是" --> AUTH
    AUTH -- "是" --> PAGE
    AUTH -- "否" --> E403["403"]
```

状态机规则：

1. 登录成功后必须再次检查页面是否存在、是否已发布，以及当前顾客是否有权访问。
2. B 端没有明确返回“可以访问”时，不得按公开页面或默认顾客权限放行。
3. 403、404 页面自身不得再次套用项目页面权限而形成循环。
4. 页面局部数据失败不重新执行整页登录，也不进入 403/404。

## 6. 核心访问场景

### UC-ACCESS-01 匿名访问公开页面

1. 顾客打开已发布页面。
2. 当前线上发布快照允许未登录访问。
3. C 端直接展示页面。

结果：不创建强制登录步骤，不要求存在 B 端顾客授权。

### UC-ACCESS-02 登录后访问受限页面

1. 顾客打开不允许匿名访问的已发布页面。
2. 当前没有有效顾客登录。
3. C 端调用登录组件，不渲染受限内容。
4. 顾客登录成功。
5. C 端用当前顾客识别编号和页面标识查询 B 端页面权限。
6. 明确允许时进入原页面。
7. C 端在当前浏览器保存顾客识别编号，供后续数据上报关联顾客。

### UC-ACCESS-03 已登录但无页面授权

1. 当前顾客登录有效。
2. B 端没有授予该顾客当前页面权限，或权限已经被撤销。
3. C 端进入 403，不展示页面标题、Widget、缩略图、联系方式或受限内容摘要。
4. 顾客可以返回来源，或清除当前登录后使用其他顾客账号重新登录。

### UC-ACCESS-04 页面不存在或已下线

1. 路由无法识别页面、项目/页面不存在、页面未发布、A 端已下线或链接无效。
2. C 端进入 404。
3. 不展示旧发布内容，不因为顾客曾经有权限而继续访问。

### UC-ACCESS-05 登录在访问中失效

1. 顾客已进入受限页面。
2. 登录过期、无效或被系统撤销。
3. C 端停止继续请求新的受限数据，调用登录组件。
4. 重新登录后再次校验页面状态和授权。
5. 权限仍有效时恢复原目标；权限被撤销时进入 403。

## 7. 访问与授权规则

### 7.1 公开访问

- `anonymous_access = true` 时，匿名顾客可直接访问当前已发布页面。
- 已登录顾客也可以访问公开页面，但登录身份不得改变页面内容范围。
- B 端页面权限检查失败不应阻断公开页面，因为公开页面不需要检查具体顾客权限。
- 页面从公开改为受限或从受限改为公开，必须由 A 端重新发布后才影响线上。

### 7.2 受限访问

- `anonymous_access = false` 时，页面内容必须在登录与授权通过后才渲染。
- C端按 B端当前顾客分享规则完成认证；具体输入、验证码和校验流程属于 B端定义，不在 C端固定。
- 认证成功只证明当前顾客身份已确认，不等于获得所有页面权限；仍须取得 B端对当前页面的明确允许。
- 顾客登录有效但页面权限结果缺失、未知、超时或明确拒绝时，不得展示受限内容。
- 明确拒绝进入 403；页面权限检查暂时失败时不得伪装为“明确无权”，应显示局部提示与重试，且不新增状态页。
- B 端根据“顾客识别编号 + 当前页面”给出最终结果；项目级、标签级或模板级规则如需换算，由 B 端完成，C 端不自行推导。
- 一个页面的授权不得自动扩大到同项目其他页面；页面导航仍需逐页消费授权结果，只显示明确可访问的页面。

### 7.3 导航可见页面

- 当前页面访问校验通过后，才可加载导航组件及其页面清单。
- 匿名顾客只看到同一页面集合中允许匿名访问的已发布页面。
- 已登录顾客只看到同一页面集合中 B 端明确允许该顾客访问的已发布页面。
- 无权限页面不得以禁用项、锁图标、标题、缩略图或数量形式出现。
- 权限过滤后没有其他页面时隐藏导航入口；不得把当前页面包装为单项菜单。
- 顾客选择导航项时仍需校验目标页面的最新发布状态和权限；目标失效时按 403/404 处理。

### 7.4 本地顾客记录与顾客切换

- 登录成功后，在当前浏览器保存系统生成的顾客识别编号、登录方式和登录是否有效。
- 验证输入不得保存；顾客邮箱如被 B端规则使用，也不作为默认数据上报参数。
- 后续增加数据上报时，有效登录顾客使用顾客识别编号关联，匿名顾客不生成该编号。
- 顾客登录可以跨三个 MVP 页面复用，但每次进入受限页面仍需检查该页面权限。
- 登录保持时间和保存方式由开发方案确定。
- 切换顾客、主动退出或登录失效时，必须清除前一顾客记录、页面临时状态和可能保存的页面权限结果。
- 公开页面不得显示前一顾客专属状态或内容。
- 顾客身份只能在同一项目内复用。进入同项目另一受限页面时不重复输入验证码，但必须静默确认当前页面授权；未明确允许时进入403。
- 顾客身份、会话、页面临时状态和已保存授权结果绝对禁止跨项目复用。进入另一项目的受限页面必须重新认证。
- C端页尾提供低频“退出登录”。退出后清除当前顾客记录和同项目临时状态；后续访问受限页必须重新认证。

### 7.5 防泄露

- 登录与权限通过前，不返回或预渲染项目名称、页面名称、封面、POI、户型、联系方式和受限内容计数。
- 403 不展示顾客缺少哪条权限、由哪个标签/模板授权、其他有权限顾客或销售人员信息。
- 404 不展示内部路由、实例 ID、项目 ID、下线原因或旧发布内容。
- 验证码、登录凭据和页面权限明细不进入访问链接、前端日志、可见错误和后续数据上报。
- 后续数据上报只使用系统生成的顾客识别编号，不直接使用顾客邮箱。

## 8. 状态归属

| 触发条件 | 顾客结果 | 归属 |
| --- | --- | --- |
| 公开页面有效 | 直接进入页面 | 页面体系 |
| 受限页面未登录 | 顾客登录组件 | 登录组件 PRD |
| 顾客分享验证失败 | 登录组件内提示与重试 | 登录组件 PRD |
| 登录失效 | 重新打开登录组件 | 登录组件 PRD |
| 页面权限检查暂时失败 | 访问检查局部提示与重试 | 本文档；不新增错误页 |
| 登录成功但无页面授权 | 403 | 06 系统状态与错误页 |
| 页面/项目不存在、未发布、已下线、链接无效 | 404 | 06 系统状态与错误页 |
| Widget 内容缺失或局部服务失败 | 页面/Widget 局部降级 | 对应页面或 Widget PRD |

## 9. 验收标准

| AC | Given | When | Then |
| --- | --- | --- | --- |
| AC-ACCESS-01 | 已发布页面允许未登录访问 | 匿名顾客打开 | 直接进入页面，不调用登录组件和 B 端页面授权。 |
| AC-ACCESS-02 | 已发布页面不允许未登录访问 | 未登录顾客打开 | 先显示登录组件，项目内容不泄露。 |
| AC-ACCESS-03 | 顾客登录成功且 B 端明确授权当前页面 | 完成校验 | 返回原目标页面，不跳转项目概览页。 |
| AC-ACCESS-04 | 顾客登录成功但无当前页面授权 | 完成校验 | 进入 403，不展示受限摘要。 |
| AC-ACCESS-05 | 顾客有页面 A 授权但没有页面 B 授权 | 直接访问页面 B | 页面 B 进入 403，不继承页面 A 权限。 |
| AC-ACCESS-06 | 页面不存在、未发布、下线或链接无效 | 任意身份访问 | 进入 404，不展示旧内容。 |
| AC-ACCESS-07 | 线上页面修改 `anonymous_access` 但未重新发布 | 顾客访问 | 继续使用上一次发布快照中的访问模式。 |
| AC-ACCESS-08 | 受限页面登录失效 | 顾客继续访问 | 调用登录组件；重新登录后再次检查页面权限。 |
| AC-ACCESS-09 | B 端未明确返回可以访问 | C 端处理结果 | 不放行，也不因异常自动授予权限。 |
| AC-ACCESS-10 | 顾客切换账号 | 新顾客登录 | 清除前一顾客记录和临时状态，再检查原页面。 |
| AC-ACCESS-11 | Google 地图、图片或单个 POI 局部失败 | 页面权限已通过 | 按 Widget 局部规则处理，不进入 403/404。 |
| AC-ACCESS-12 | 检查页面响应、日志和可见错误 | 访问成功或失败 | 不泄露验证码、登录凭据、内部顾客编号、权限来源或受限内容。 |
| AC-ACCESS-13 | 受限页面没有有效顾客认证 | 登录组件打开 | C端按 B端提供的分享验证规则展示必要输入和反馈，不写死邮箱、密码或免验证分支。 |
| AC-ACCESS-14 | 顾客分享验证成功 | 继续访问受限页面 | C端仍检查当前页面授权；不得把认证成功当作全项目或全页面放行。 |
| AC-ACCESS-17 | 任一种登录成功 | 检查浏览器本地记录 | 保存顾客识别编号，不保存密码，不把邮箱作为默认上报参数。 |
| AC-ACCESS-18 | 顾客切换、退出或登录失效 | 状态变化 | 清除原顾客记录，后续不得继续关联原顾客。 |
| AC-ACCESS-19 | 同一顾客在同一项目打开多个受限页面 | 进入另一页面 | 不重复输入验证码，但 C端静默确认当前页面授权；未授权进入 403。 |
| AC-ACCESS-20 | 顾客进入另一项目受限页面 | 打开页面 | 不复用任何身份、会话、临时状态或页面授权结果，重新按 B端规则认证。 |
| AC-ACCESS-21 | 页面集合中包含当前顾客无权访问的页面 | 打开全屏导航 | 无权限页面名称、摘要和禁用项均不显示。 |
| AC-ACCESS-22 | 匿名顾客打开公开页面 | 打开全屏导航 | 只显示同集合内允许匿名访问的页面。 |
| AC-ACCESS-23 | 导航清单加载完成后目标页面权限被撤销 | 顾客选择目标 | 重新校验并进入 403，不展示目标页面内容。 |

## 10. MVP 明确不做

- 页面实例有效期、单次分享链接有效期或访问次数限制。
- A 端选择具体顾客、B 端权限管理界面和顾客账号创建流程。
- 修改 B端顾客分享验证、顾客管理和分享链接生成流程，或在 C端定义验证码具体规则。
- C 端自行推导标签、模板、项目级权限或默认权限。
- 组件级、字段级或单个 POI/户型级顾客权限。
- 顾客角色体系、管理员/销售登录和内部预览身份。
- 注册、找回/重置密码、社交登录、顾客中心和全局账号菜单。
- 权限日志报表、分享追踪、CRM、销售归属和实际数据上报；MVP 只保存后续上报所需的顾客识别编号。
- 401、410、429、500、502、503、504 等产品状态页。

## 11. C端承接现有B端结果

- 直接复用现有 B 端分享验证结果，不以 C 端 MVP 为由调整原有业务流程。
- C端读取现有结果中的顾客分享验证规则、验证结果、顾客识别编号和页面访问结果。
- B 端没有明确返回可以访问时，C 端不能展示受限页面。
- 如果 B 端现有名称与本文档不同，开发时只做含义对应，不要求修改 B 端业务名称或操作流程。
- A 端当前 `anonymous_access` 发布快照规则可直接复用，无需把具体顾客授权加入 A 端页面配置。
- 页面权限检查失败后的重试次数和等待时间由开发方案确定，但不得改变“没有明确允许就不展示受限内容”的规则。

## 12. 供 Codex 使用的执行说明

- 先判断页面是否存在和已发布，再读取当前发布快照的访问模式。
- 未登录先调用登录组件；不要把未登录写成 403。
- 登录成功后必须单独检查当前页面权限；不要把登录成功写成自动放行。
- 不得在 C端根据链接参数推断、配置或覆盖 B端顾客分享验证规则。
- 不得为了 C 端实现方便反向修改 B 端已有分享验证流程。
- 登录成功后保存最少的顾客识别信息；密码不得保存，邮箱默认不用于数据上报。
- 页面无权限用 403，页面不存在/未发布/下线/链接无效用 404。
- 不得把权限判断复制进三个 Widget 或项目联系组件。
