为内嵌管理页增加轻量登录与 API 认证 #4

Open
opened 2026-08-28 12:01:09 +08:00 by ila · 1 comment
Owner

原始需求

  • 来源与时间:用户会话,2026-08-28
  • 关键原话或脱敏摘要:为内嵌原生轻量管理页增加 simple and light 登录;账号密码由本地 mediamtx.yml 管理;当前使用 HTTP,允许局域网访问,HTTPS 后续再做。

目标

  • 为 /admin/ 提供无框架、原生 HTML/CSS/JS 登录页。
  • 使用 MediaMTX 现有 authMethod: internal、authInternalUsers 和 action: api 权限认证。
  • 登录后复用现有管理功能;支持当前标签页会话、认证失败反馈和显式退出。
  • 保持 HTTP 局域网访问能力。

非目标

  • 本工单不增加 HTTPS、证书管理、Nginx/Caddy 代理、外部身份提供商、服务端 Session 或用户数据库。
  • 不改变 RTSP/HLS/WebRTC 的 publish/read 权限策略。
  • 不把真实账号、密码、摄像头 URL 或其他密钥写入工单、测试或 Git 提交。

已确认方案

  1. /admin 与 /admin/* 静态资源可匿名加载,/v3/* Control API 继续强制执行 MediaMTX 认证中间件。
  2. 登录表单收集用户名和密码,以 HTTP Basic Authorization 调用只读 API 验证。
  3. 验证成功后只在 sessionStorage 保存当前标签页所需的 Authorization 值;刷新保留,关闭标签页清除。
  4. 所有管理 API 请求统一附加 Authorization;收到 401 时清除会话并返回登录态。
  5. 提供退出按钮、密码显隐、提交中状态、可访问标签、键盘操作和内联错误。
  6. 用户接受当前阶段 HTTP 在可信局域网使用的风险;页面明确提示“HTTP 不加密”,后续单独建设 HTTPS。
  7. 本地 mediamtx.yml 使用命名管理员和 action: api;真实凭据不纳入提交。

前置工单

  • #3 实现内嵌原生轻量 RTSP 管理页面:本工单基于其现有 /admin/ 页面继续增量实现。#3 当前待验收,不改变其 RTSP 源管理范围。

影响范围

  • internal/api/api.go:管理静态资源与 API 认证中间件的路由边界。
  • internal/api/admin/*:登录、会话、退出和认证请求。
  • internal/api/*_test.go:认证路由、登录静态资源及 API 401/成功行为。
  • 本地 mediamtx.yml:命名管理员配置(不提交真实凭据)。

风险与安全边界

  • HTTP Basic 在 HTTP 上传输时可被同网段观察者获取;仅适用于用户确认的可信局域网,禁止公网/NAT 暴露。
  • sessionStorage 不是服务端 Session;其目的仅是避免持久化到磁盘,不能替代 HTTPS。
  • 管理静态资源匿名不等于 API 匿名;测试必须证明未认证 /v3/* 返回 401。
  • 不在日志、错误信息、页面或工单回显密码及完整 Authorization。

回退方式

  • 回退本工单提交即可恢复浏览器原生 Basic Auth 行为和原管理页。
  • 本地管理员配置可恢复为原来的 localhost 匿名 API 权限。

验收标准

  • 未登录访问 /admin/ 能显示登录页,不触发浏览器原生认证弹窗
  • 错误凭据显示明确错误且不进入管理页
  • 正确 action: api 凭据可进入现有管理页并执行原功能
  • 刷新保留当前标签页登录,退出后 API 请求不再携带凭据
  • 未认证 /v3/* 仍返回 401
  • 375px 与桌面宽度可用,标签、焦点、错误提示符合基础无障碍要求
  • 受影响 Go 与前端测试通过
  • 真实凭据未进入提交、测试、日志和工单
  • 文档影响已处理

验证方法

  • Go 路由与认证测试:匿名管理页资源、匿名 API 401、正确/错误 Basic 凭据。
  • 前端逻辑测试:登录状态、Authorization 注入、401 清理、退出。
  • 本地构建后以虚构测试账号启动,使用 curl 验证 HTTP 状态;浏览器验证 375px 与桌面交互。
  • 运行 go test ./internal/api ./internal/core、相关前端测试和 python dev_scripts/harness.py check --strict。

设计证据

本次为已确认管理页面上的单一轻量登录状态,不新增信息架构。用户于 2026-08-28 明确确认:HTTP、允许局域网、HTTPS 后续。UI 采用现有页面视觉语言,单一主操作、可见标签、密码显隐、内联错误、提交中禁用、44px 触控目标和可见焦点;无需另建完整原型。

文档影响

登录与 HTTP 局域网安全边界属于长期产品事实。实现完成后更新 Gitea Wiki 的 Product-Requirements-Overview / Architecture-and-Code-Map / Troubleshooting,并同步 docs/maintainer/ 镜像;禁止直接编辑镜像。

实施结果

  • 提交:18f5196c137cc99080089d9421d89b50549c8d63
  • 已推送:origin/main
  • 路由:/admin/* 匿名加载登录外壳;/v3/* 保持 action: api 强制认证。
  • 前端:当前标签页会话、Authorization 注入、401 清理、密码显隐、提交状态、错误反馈、退出。
  • 本地配置:生成命名管理员供用户使用;真实凭据与摄像头配置未提交。
  • 文档:Wiki 与 docs/maintainer 镜像已同步。

验证结果

  • node --check internal/api/admin/app.js:通过。
  • go test ./internal/api -run '^TestAdmin' -count=1:通过。
  • go test ./internal/core -run '^:编译通过。
  • go build ./...:通过。
  • HTTP 集成:管理页 200;匿名 API 401 且返回 Basic challenge;错误凭据 401;正确凭据 200。
  • 浏览器:桌面与 375px 无横向溢出;错误登录提示、正确登录、管理页、退出和刷新后保持退出均通过;控制台错误 0。
  • DevHarness:check --strict 与 Wiki sync --check 通过。
  • 安全扫描:候选提交不包含摄像头主机、密码或临时测试账号。
  • 未覆盖:go test ./internal/api 与 go test ./internal/core 全包运行被本机已有 MediaMTX 占用固定测试端口(含 9997、8000、1935)阻断;失败均为 bind 冲突,已由聚焦测试、编译和真实独立端口集成覆盖本单风险。

文档证据

  • Product-Requirements-Overview:736e3cdfaa941073735475ac5a2b8962ed9ed566
  • Architecture-and-Code-Map:6991cffa6aea712d358645cf0942550bd277175a
  • Troubleshooting:1a3d725f5518e3cbed93760a58385af21ca34f92

状态

实现完成,待用户验收

## 原始需求 - 来源与时间:用户会话,2026-08-28 - 关键原话或脱敏摘要:为内嵌原生轻量管理页增加 simple and light 登录;账号密码由本地 `mediamtx.yml` 管理;当前使用 HTTP,允许局域网访问,HTTPS 后续再做。 ## 目标 - 为 `/admin/` 提供无框架、原生 HTML/CSS/JS 登录页。 - 使用 MediaMTX 现有 `authMethod: internal`、`authInternalUsers` 和 `action: api` 权限认证。 - 登录后复用现有管理功能;支持当前标签页会话、认证失败反馈和显式退出。 - 保持 HTTP 局域网访问能力。 ## 非目标 - 本工单不增加 HTTPS、证书管理、Nginx/Caddy 代理、外部身份提供商、服务端 Session 或用户数据库。 - 不改变 RTSP/HLS/WebRTC 的 publish/read 权限策略。 - 不把真实账号、密码、摄像头 URL 或其他密钥写入工单、测试或 Git 提交。 ## 已确认方案 1. `/admin` 与 `/admin/*` 静态资源可匿名加载,`/v3/*` Control API 继续强制执行 MediaMTX 认证中间件。 2. 登录表单收集用户名和密码,以 HTTP Basic Authorization 调用只读 API 验证。 3. 验证成功后只在 `sessionStorage` 保存当前标签页所需的 Authorization 值;刷新保留,关闭标签页清除。 4. 所有管理 API 请求统一附加 Authorization;收到 401 时清除会话并返回登录态。 5. 提供退出按钮、密码显隐、提交中状态、可访问标签、键盘操作和内联错误。 6. 用户接受当前阶段 HTTP 在可信局域网使用的风险;页面明确提示“HTTP 不加密”,后续单独建设 HTTPS。 7. 本地 `mediamtx.yml` 使用命名管理员和 `action: api`;真实凭据不纳入提交。 ## 前置工单 - #3 实现内嵌原生轻量 RTSP 管理页面:本工单基于其现有 `/admin/` 页面继续增量实现。#3 当前待验收,不改变其 RTSP 源管理范围。 ## 影响范围 - `internal/api/api.go`:管理静态资源与 API 认证中间件的路由边界。 - `internal/api/admin/*`:登录、会话、退出和认证请求。 - `internal/api/*_test.go`:认证路由、登录静态资源及 API 401/成功行为。 - 本地 `mediamtx.yml`:命名管理员配置(不提交真实凭据)。 ## 风险与安全边界 - HTTP Basic 在 HTTP 上传输时可被同网段观察者获取;仅适用于用户确认的可信局域网,禁止公网/NAT 暴露。 - `sessionStorage` 不是服务端 Session;其目的仅是避免持久化到磁盘,不能替代 HTTPS。 - 管理静态资源匿名不等于 API 匿名;测试必须证明未认证 `/v3/*` 返回 401。 - 不在日志、错误信息、页面或工单回显密码及完整 Authorization。 ## 回退方式 - 回退本工单提交即可恢复浏览器原生 Basic Auth 行为和原管理页。 - 本地管理员配置可恢复为原来的 localhost 匿名 API 权限。 ## 验收标准 - [x] 未登录访问 `/admin/` 能显示登录页,不触发浏览器原生认证弹窗 - [x] 错误凭据显示明确错误且不进入管理页 - [x] 正确 `action: api` 凭据可进入现有管理页并执行原功能 - [x] 刷新保留当前标签页登录,退出后 API 请求不再携带凭据 - [x] 未认证 `/v3/*` 仍返回 401 - [x] 375px 与桌面宽度可用,标签、焦点、错误提示符合基础无障碍要求 - [x] 受影响 Go 与前端测试通过 - [x] 真实凭据未进入提交、测试、日志和工单 - [x] 文档影响已处理 ## 验证方法 - Go 路由与认证测试:匿名管理页资源、匿名 API 401、正确/错误 Basic 凭据。 - 前端逻辑测试:登录状态、Authorization 注入、401 清理、退出。 - 本地构建后以虚构测试账号启动,使用 curl 验证 HTTP 状态;浏览器验证 375px 与桌面交互。 - 运行 `go test ./internal/api ./internal/core`、相关前端测试和 `python dev_scripts/harness.py check --strict`。 ## 设计证据 本次为已确认管理页面上的单一轻量登录状态,不新增信息架构。用户于 2026-08-28 明确确认:HTTP、允许局域网、HTTPS 后续。UI 采用现有页面视觉语言,单一主操作、可见标签、密码显隐、内联错误、提交中禁用、44px 触控目标和可见焦点;无需另建完整原型。 ## 文档影响 登录与 HTTP 局域网安全边界属于长期产品事实。实现完成后更新 Gitea Wiki 的 Product-Requirements-Overview / Architecture-and-Code-Map / Troubleshooting,并同步 `docs/maintainer/` 镜像;禁止直接编辑镜像。 ## 实施结果 - 提交:`18f5196c137cc99080089d9421d89b50549c8d63` - 已推送:`origin/main` - 路由:`/admin/*` 匿名加载登录外壳;`/v3/*` 保持 `action: api` 强制认证。 - 前端:当前标签页会话、Authorization 注入、401 清理、密码显隐、提交状态、错误反馈、退出。 - 本地配置:生成命名管理员供用户使用;真实凭据与摄像头配置未提交。 - 文档:Wiki 与 `docs/maintainer` 镜像已同步。 ## 验证结果 - `node --check internal/api/admin/app.js`:通过。 - `go test ./internal/api -run '^TestAdmin' -count=1`:通过。 - `go test ./internal/core -run '^`:编译通过。 - `go build ./...`:通过。 - HTTP 集成:管理页 200;匿名 API 401 且返回 Basic challenge;错误凭据 401;正确凭据 200。 - 浏览器:桌面与 375px 无横向溢出;错误登录提示、正确登录、管理页、退出和刷新后保持退出均通过;控制台错误 0。 - DevHarness:`check --strict` 与 Wiki `sync --check` 通过。 - 安全扫描:候选提交不包含摄像头主机、密码或临时测试账号。 - 未覆盖:`go test ./internal/api` 与 `go test ./internal/core` 全包运行被本机已有 MediaMTX 占用固定测试端口(含 9997、8000、1935)阻断;失败均为 bind 冲突,已由聚焦测试、编译和真实独立端口集成覆盖本单风险。 ## 文档证据 - Product-Requirements-Overview:`736e3cdfaa941073735475ac5a2b8962ed9ed566` - Architecture-and-Code-Map:`6991cffa6aea712d358645cf0942550bd277175a` - Troubleshooting:`1a3d725f5518e3cbed93760a58385af21ca34f92` ## 状态 实现完成,待用户验收
Author
Owner

工单 #4 已完成实现并推送。

  • Commit: 18f5196c
  • 登录页、API 认证边界、当前标签页会话、401 清理与退出均已验证。
  • 375px / 桌面浏览器检查通过,控制台错误为 0。
  • Wiki 与维护镜像已同步。
  • 本地管理员密码、摄像头配置、EXE、启动脚本及用户原有无关改动均未进入提交。
  • 全包测试受本机既有 MediaMTX 固定端口占用影响;聚焦测试、编译和独立端口真实集成均通过。

状态保持为“实现完成,待用户验收”,工单不关闭。

工单 #4 已完成实现并推送。 - Commit: [`18f5196c`](https://git.ilapage.cn/OPC/mediamtx/commit/18f5196c137cc99080089d9421d89b50549c8d63) - 登录页、API 认证边界、当前标签页会话、401 清理与退出均已验证。 - 375px / 桌面浏览器检查通过,控制台错误为 0。 - Wiki 与维护镜像已同步。 - 本地管理员密码、摄像头配置、EXE、启动脚本及用户原有无关改动均未进入提交。 - 全包测试受本机既有 MediaMTX 固定端口占用影响;聚焦测试、编译和独立端口真实集成均通过。 状态保持为“实现完成,待用户验收”,工单不关闭。
Sign in to join this conversation.
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: OPC/mediamtx#4