Files
AIclinicalresearch/docs/03-业务模块/RVW-稿件审查系统/00-系统设计/V3.0/AI智能审稿域名与多租户技术指南.md
HaHafeng 16179e16ca feat(rvw): deliver tenant portal v4 flow and config foundation
Implement RVW V4.0 tenant-aware backend/frontend flow with tenant routing, config APIs, and full portal UX updates. Sync system/RVW/deployment docs to capture verified upload-review-report workflow and next-step admin configuration work.

Made-with: Cursor
2026-03-14 22:29:40 +08:00

6.2 KiB
Raw Blame History

AI智能审稿系统 (期刊SaaS版) 域名架构与多租户落地技术指南

文档受众: 架构师、前端研发、后端研发、运维工程师

文档目的: 明确期刊 SaaS 业务的域名规范规范单点登录SSO及多租户鉴权的开发标准排查并规避泛域名 SSL 证书与第三方回调等运维/安全隐患。

🏗️ 一、 核心架构决策:三级子域名隔离方案

经过商业定位与工程复杂度的综合评估,系统采用基于功能属性的三级子域名方案

[tenantId].review.xunzhengyixue.com (例如jtim.review.xunzhengyixue.com)

为什么选择这个方案?

  1. 商业心智精准:使用 review 明确了我们是“AI 辅助审稿工具”,而非沉重的全流程投审稿系统,降低客户防备心。
  2. 品牌与视觉隔离:彻底抛弃 URL路径隔离为每个期刊提供独立的门户网址。
  3. 架构解耦:与现有的临床研究主站(.yanjiu. 或主域)及临床试验项目(.iit.)在命名空间上完美平行,为未来的 SaaS 矩阵拓展留足空间。

🛠️ 二、 运维团队 (DevOps) 执行清单

运维团队需在阿里云环境中完成以下配置,该方案无需为每个新增期刊重新发布或修改配置

1. DNS 云解析配置 (阿里云)

无需每次新增期刊都修改 DNS。请添加一条泛解析记录:

  • 主机记录*.review
  • 记录类型A 或 CNAME
  • 记录值:指向 SAE 现有的前端 CLB 负载均衡公网 IP目前为 8.140.53.236)。

2. ⚠️ 致命避坑SSL 证书采购与挂载

  • 红线提醒:现有的 *.xunzhengyixue.com 泛域名证书绝对无法覆盖四级域名(即无法覆盖 jtim.review.xunzhengyixue.com直接使用会导致浏览器报红。
  • 执行动作:必须重新申请/购买一张专门针对 *.review.xunzhengyixue.com 的泛域名 SSL 证书,并挂载到网关或 CLB 上。

3. Nginx 路由代理配置

前端 frontend-v2 镜像的 nginx.conf 需要配置匹配规则,将所有子域名的请求导向同一个 SPA单页应用入口API 请求依然打向 Node.js 后端。

server {
listen 80;
# 匹配所有的 review 子域名
server_name ~^(?<tenant>.+)\.review\.xunzhengyixue\.com$;

location / {  
    root /usr/share/nginx/html;  
    index index.html;  
    \# 将所有未匹配静态资源的路由回退给 index.html交由 React Router 处理  
    try\_files $uri $uri/ /index.html;   
}  
  
\# 后端 API 转发保持现有配置不变  
location /api/ {  
    proxy\_pass \[http://172.17.173.73:3001\](http://172.17.173.73:3001);   
    \# ...  
}  

}

💻 三、 前端研发 (FE) 执行清单

前端代码库保持同一套,依靠初始化时截取 window.location.hostname 来实现“千刊千面”。

1. 动态截取 TenantID

在应用挂载层(如 App.tsx 或路由初始化钩子中)注入租户识别逻辑:

const host = window.location.hostname; // e.g., jtim.review.xunzhengyixue.com
let currentTenantId = 'default';

// 严格判断当前是否处于期刊审查工作台环境
if (host.endsWith('.review.xunzhengyixue.com')) {
// 提取第一个分段作为 tenantId
currentTenantId = host.split('.')[0];
}

// 拿到 currentTenantId (如 'jtim') 后:
// 1. 发起请求GET /api/v1/tenants/public-info/jtim 获取 Logo、主题色
// 2. 存入全局状态 (Zustand/Redux),应用定制化 UI

2. 模块级路由屏蔽

利用现有的 moduleRegistry.ts如果当前 tenantId 为期刊客户,隐藏顶部导航中的 AIA、DC、PKB 模块,仅暴露 RVW 模块视图。

⚙️ 四、 后端研发 (BE) 执行清单

后端核心挑战在于跨域资源共享 (CORS) 以及 防范多租户架构下的数据越权

1. CORS 动态白名单

禁止写死 Origin在 Fastify / Express 的 CORS 插件中启用正则匹配:

// 允许主站以及所有的 review 泛域名跨域访问
cors: {
origin: [
/^https?:\/\/([a-zA-Z0-9-]+\.)?xunzhengyixue\.com$/,
/^https?:\/\/([a-zA-Z0-9-]+\.)?review\.xunzhengyixue\.com$/
],
credentials: true
}

2. ⚠️ 致命避坑SSO 单点登录与防越权 (IDOR 防护)

由于我们采用底层复用 platform_schema.users 的机制JWT Cookie 会在主域下共享。这带来极大的越权风险。

  • SSO 签发:登录时,后端校验用户身份后,必须将当前所在的 tenantId 压入 JWT Payload。
  • 双重校验防线 (必须写进中间件 auth.middleware.ts)
    当一个请求打到 /api/v2/rvw/tasks 时,中间件必须校验两件事:
    1. Token 解析出的 userId 是否有效。
    2. 跨域校验:该用户是否有权限访问当前 HTTP 请求 Header 中声明的 x-tenant-id或者通过请求域名解析出的 tenant。如果张医生是 iit 的用户,但拿着 Token 试图请求 jtim 租户的数据,必须直接拦截并返回 403 Forbidden
  • ORM 级隔离:所有针对 RVW 模块的 Prisma 查询,必须强制附带 where: { tenantId: request.tenantId },严禁“裸查”。

🔮 五、 未来架构扩展预警:第三方登录限制

【风险说明】

如果您未来计划在 jtim.review... 等域名上引入“微信扫码登录”或微信支付。微信开放平台的安全机制通常要求配置绝对精准的回调域名,往往不支持通配符(*.review...),且回调域名数量有严格上限。

【架构预案:统一认证网关】

为了应对该问题,平台在未来演进时,应规划统一的 Auth Center

  1. 任何期刊页面点击“微信登录”,统一 302 Redirect 跳转至主站网关(如 login.xunzhengyixue.com/wechat
  2. 主站统一处理微信回调,生成系统内部的 JWT SSO Token。
  3. 主站将 Token 携带在参数或安全 Cookie 中,再次 302 Redirect 飞回 jtim.review.xunzhengyixue.com/callback完成身份同步。
    (目前 MVP 阶段账号密码登录不受此限制,仅作未来规划记录)。