Files
model-platform/contracts/runtime/jupyter-proxy-v1.md
T

2.5 KiB
Raw Blame History

Jupyter 代理与访问票据契约 V1

1. 浏览器访问流程

  1. 前端携带用户、Workspace、edit_session_idlock_token 调用 POST /api/v1/jupyter/access-tickets
  2. Platform API 校验编辑锁、Runtime 与 Jupyter Session 的归属及状态。
  3. 成功后返回 /jupyter/... 地址,并设置短期 jupyter_access Cookie。
  4. 前端在当前平台页面的编辑区内嵌同源 /jupyter/... 页面,不新开浏览器 标签页。
  5. 内嵌页面经 Nginx 访问 Jupyter HTTP/WebSocketNginx 先执行内部鉴权 子请求,再把内部 Token 注入上游请求。

一个 Workspace 只建立或复用一个 Jupyter Runtime/Server;同一 Server 中的每个 Notebook 使用独立 Jupyter Session 和独立 Kernel。

浏览器响应、URL、JavaScript 和日志中都不得出现 Jupyter 内部 Token。

2. 访问票据

  • 票据绑定:user_idworkspace_idedit_session_idruntime_idjupyter_session_id
  • 默认有效期:60 秒;最长不超过 5 分钟。
  • CookieHttpOnly; SameSite=Lax; Path=/jupyter/,生产环境必须增加 Secure
  • 票据只授权当前 Workspace 的 Jupyter 路径,不能跨 Workspace 使用。
  • Jupyter 页面必须与平台使用同一站点入口,并允许同源 iframe 嵌入。

3. Nginx 内部鉴权接口

GET /internal/v1/jupyter/authorize
Cookie: jupyter_access=<opaque-ticket>
X-Original-URI: /jupyter/...
X-Request-ID: <request-id>

该接口只允许 Nginx 在内部网络调用:

  • 204:票据有效,响应头提供上游地址和内部认证信息。
  • 401:票据缺失、伪造或过期。
  • 403:用户、Workspace、Session 不匹配,或编辑锁/Runtime 已失效。

成功响应头:

X-Jupyter-Upstream: http://jupyter:8888
X-Jupyter-Authorization: token <internal-token>
X-Workspace-ID: <workspace-id>

Nginx 必须删除客户端传入的 Authorization,使用内部鉴权结果重建上游 认证头。

4. WebSocket 约束

  • /jupyter/api/kernels/*/channels 与其他 WebSocket 路径使用 HTTP/1.1。
  • 转发 UpgradeConnectionHostOrigin 和请求 ID。
  • 关闭代理缓冲,读超时不小于 3600 秒。
  • HTTP 和 WebSocket 使用同一票据校验规则。
  • 连接关闭只断开交互连接,不自动停止 Workspace Runtime。
  • Compose Demo 使用最长 5 分钟票据;前端必须继续发送编辑锁心跳,并在 票据到期前重新签发。
  • Jupyter Lab HTML 中出现的内部 Token 必须由 Nginx 在返回浏览器前清除。