diff --git a/Sense/server/app/sense/identity/password.go b/Sense/server/app/sense/identity/password.go index d8bfe44..bc422ec 100644 --- a/Sense/server/app/sense/identity/password.go +++ b/Sense/server/app/sense/identity/password.go @@ -2,28 +2,14 @@ package identity import ( "fmt" - "strings" - "unicode" "golang.org/x/crypto/bcrypt" ) -func ValidatePassword(username, password string) error { +func ValidatePassword(_ string, password string) error { if len([]rune(password)) < 6 { return fmt.Errorf("密码至少需要 6 个字符") } - var upper, lower, digit bool - for _, value := range password { - upper = upper || unicode.IsUpper(value) - lower = lower || unicode.IsLower(value) - digit = digit || unicode.IsDigit(value) - } - if !upper || !lower || !digit { - return fmt.Errorf("密码必须同时包含大写字母、小写字母和数字") - } - if username != "" && strings.Contains(strings.ToLower(password), strings.ToLower(username)) { - return fmt.Errorf("密码不能包含用户名") - } return nil } diff --git a/Sense/server/app/sense/identity/password_test.go b/Sense/server/app/sense/identity/password_test.go index a090d10..0308d36 100644 --- a/Sense/server/app/sense/identity/password_test.go +++ b/Sense/server/app/sense/identity/password_test.go @@ -12,12 +12,10 @@ func TestValidatePasswordLengthAndComplexity(t *testing.T) { password string want string }{ - {name: "six characters", username: "operator", password: "Abc123"}, + {name: "six lowercase characters", username: "operator", password: "abcdef"}, + {name: "contains username", username: "admin", password: "admin123"}, + {name: "six unicode characters", username: "operator", password: "密码密码密码"}, {name: "five characters", username: "operator", password: "Ab123", want: "至少需要 6 个字符"}, - {name: "missing uppercase", username: "operator", password: "abc123", want: "大写字母、小写字母和数字"}, - {name: "missing lowercase", username: "operator", password: "ABC123", want: "大写字母、小写字母和数字"}, - {name: "missing digit", username: "operator", password: "Abcdef", want: "大写字母、小写字母和数字"}, - {name: "contains username", username: "admin", password: "MyAdmin1", want: "不能包含用户名"}, } for _, test := range tests { diff --git a/Sense/ui/src/views/sense/identity/Users.vue b/Sense/ui/src/views/sense/identity/Users.vue index 139f660..92b39bf 100644 --- a/Sense/ui/src/views/sense/identity/Users.vue +++ b/Sense/ui/src/views/sense/identity/Users.vue @@ -30,7 +30,7 @@ -
至少 6 位,包含大小写字母和数字,且不含用户名。
+
至少 6 位字符。
diff --git a/docs/03-business-rules-and-glossary.md b/docs/03-business-rules-and-glossary.md index 285b8de..6367d26 100644 --- a/docs/03-business-rules-and-glossary.md +++ b/docs/03-business-rules-and-glossary.md @@ -2,8 +2,8 @@ generated: true (请先修改 Gitea Wiki,禁止直接编辑本文件) wiki_page: Business-Rules-and-Glossary wiki_url: https://git.ilapage.cn/ila/yovision/wiki/Business-Rules-and-Glossary.- -wiki_revision: fbb85952429813bb3da7e3cd8526ec03bc0dac0d -synchronized_at: 2026-08-13T00:52:39Z +wiki_revision: c9d47108e45f66875726e3eef79eedb2a5942514 +synchronized_at: 2026-08-13T01:15:01Z # 业务规则与术语 @@ -71,7 +71,7 @@ synchronized_at: 2026-08-13T00:52:39Z ## Sense MVP 业务与安全规则 - **Sense 账户**:只登录 Sense;不得接受 Bell JWT、Cookie 或用户数据。角色为系统管理员、实施/运维、站点管理员和只读用户,后端权限是最终边界。 -- **安全初始化**:系统不提供默认账户、默认密码或默认签名密钥;首次管理员由仓库外一次性令牌创建。所有模式的密码至少 6 个字符,必须同时包含大写字母、小写字母和数字,且不得包含用户名。该最短长度由负责人在已知生产安全风险后明确确认。 +- **安全初始化**:系统不提供默认账户、默认密码或默认签名密钥;首次管理员由仓库外一次性令牌创建。所有模式的密码仅要求至少 6 个字符,不限制字符种类并允许包含用户名。负责人已明确接受该生产密码策略的字典猜测与凭据填充风险。 - **Device**:设备不可变逻辑 ID 是后续 Profile、媒体和区域的内部引用。非视频适配器未实现时必须显示 `adapter_not_ready`。 - **摄像机凭据**:只写不读,使用仓库外 32 字节密钥加密;不得进入 URL、日志、审计、工单或响应。 - **受控发现**:ONVIF Discovery 默认关闭,只有显式设置获准本机 IP 才能发送发现;不得扫描未授权网段。 diff --git a/docs/delivery/README.md b/docs/delivery/README.md index 16d425c..4569c73 100644 --- a/docs/delivery/README.md +++ b/docs/delivery/README.md @@ -2,8 +2,8 @@ generated: true (请先修改 Gitea Wiki,禁止直接编辑本文件) wiki_page: Delivery-Documentation-Guide wiki_url: https://git.ilapage.cn/ila/yovision/wiki/Delivery-Documentation-Guide.- -wiki_revision: 2cf0a0f2f261c002866c86c4e70b5f6ed89f9c1c -synchronized_at: 2026-08-13T00:53:04Z +wiki_revision: 04d9a7f0916262c3578e7934a2e98327dae55c7a +synchronized_at: 2026-08-13T01:15:15Z # 交付文档指南 @@ -84,7 +84,7 @@ synchronized_at: 2026-08-13T00:53:04Z Sense 面向网管、实施人员和非技术现场人员,菜单按日常任务组织:工作台 → 设备管理 → 视频接入 → 视频服务 → 实时监看 → 区域与警戒线。普通操作优先展示中文状态与下一步,不要求用户理解 ONVIF、RTSP 或 MediaMTX 内部模型。 -- 系统管理员:完成一次性安全初始化,维护 Sense 用户与角色,查看操作记录。首次管理员和新用户密码至少 6 个字符,必须同时包含大写字母、小写字母和数字,且不得包含用户名。 +- 系统管理员:完成一次性安全初始化,维护 Sense 用户与角色,查看操作记录。首次管理员和新用户密码仅要求至少 6 个字符,不限制字符种类并允许包含用户名;仍应由管理员选择难猜且不复用的密码。 - 实施/运维:添加设备、只写更新凭据、在获准网卡发现或手工接入、检查主辅码流、处理媒体进程与对账。 - 站点管理员:查看/维护站点设备,实时监看,绘制和发布区域版本;无权创建系统管理员。 - 只读用户:查看设备、媒体状态、实时画面和区域,不能修改。 diff --git a/docs/task/42-Sense密码策略仅限制最短6位.md b/docs/task/42-Sense密码策略仅限制最短6位.md new file mode 100644 index 0000000..462dbb7 --- /dev/null +++ b/docs/task/42-Sense密码策略仅限制最短6位.md @@ -0,0 +1,71 @@ + +generated: true (请先修改 Gitea Wiki,禁止直接编辑本文件) +wiki_page: Task-42-Sense密码策略仅限制最短6位 +wiki_url: https://git.ilapage.cn/ila/yovision/wiki/Task-42-Sense%E5%AF%86%E7%A0%81%E7%AD%96%E7%95%A5%E4%BB%85%E9%99%90%E5%88%B6%E6%9C%80%E7%9F%AD6%E4%BD%8D.- +wiki_revision: 53d52a17ae17072e1335b8bdff30fa19ad50f20f +synchronized_at: 2026-08-13T01:20:24Z + + +# 42 Sense密码策略仅限制最短6位 + +- 类型:需求变更 +- 所属 Epic:#7 +- 所属 MVP / 版本:#8 +- 状态:待验收 +- 日期:2026-08-13 +- Gitea 工单:https://git.ilapage.cn/ila/yovision/issues/42 +- Wiki 页面:Task-42-Sense密码策略仅限制最短6位 +- Wiki revision:见本地镜像头 + +## 背景与目标 + +负责人确认 Sense demo 与生产密码仅要求至少 6 个字符,取消字符种类和用户名包含限制,以支持用户指定的简单管理员凭据。实际账号和密码属于运行时秘密,不进入本归档。 + +## 最终方案 + +- 后端 `ValidatePassword` 只按 Unicode 字符数检查至少 6 个字符;bootstrap 与创建用户继续共享该入口。 +- 测试覆盖 6 位全小写、包含用户名和 6 个 Unicode 字符通过,以及 5 字符拒绝。 +- 前端新用户表单只提示“至少 6 位字符”。 +- Wiki 记录全模式规则和明确接受的风险,交付说明仍建议选择难猜且不复用的密码。 +- 重新生成 Windows 包,使用运行时注入的脱敏凭据完成 demo 管理员初始化和登录,服务保持运行。 + +## 修改文件 + +- `Sense/server/app/sense/identity/password.go` +- `Sense/server/app/sense/identity/password_test.go` +- `Sense/ui/src/views/sense/identity/Users.vue` +- `docs/03-business-rules-and-glossary.md` +- `docs/delivery/README.md` +- `wiki-docs.json` +- `docs/task/42-Sense密码策略仅限制最短6位.md` + +## 验收结果 + +| 验收标准 | 结果 | +|---|---| +| 6 位全小写密码通过,5 位拒绝 | 通过 | +| 包含用户名密码通过 | 通过 | +| bootstrap 与创建用户共享规则 | 通过 | +| 前端只提示至少 6 位 | 通过 | +| Windows ZIP 重建并完成管理员初始化/登录 | 通过;bootstrap 201,login 200 | +| 凭据不进入仓库、Wiki、工单或日志 | 通过;工单需求已脱敏 | + +## 测试 + +- `go test ./app/sense/identity/...`、`go test ./...`:通过。 +- `corepack pnpm@9.15.1 lint`:0 error,存在既有格式 warning。 +- `cmd /c Sense\scripts\package-windows.bat`:通过;前端仅有既有 vendor bundle 体积警告。 +- ZIP:7,280,519 bytes;SHA-256 `7A1DC3378ECAD90DC7521F1E49C7A279E4C31B38D6EBC8CC30E123528BECDEE4`。 +- 包内 demo:管理员初始化 201、登录 200;服务监听 `127.0.0.1:18080`。 +- Harness:31 项测试、strict 和 Wiki 镜像检查通过。 +- **未验证部分**:未在真实 PostgreSQL 环境验证;未由目标管理员人工页面登录验收。生产弱密码风险为负责人明确接受的产品决策。 + +## 遗留问题 + +- 本策略显著增加字典猜测和凭据填充风险;当前未增加 MFA、登录限速或外部身份提供者。 + +## 相关提交 + +- `8091fbb` feat: simplify Sense password policy (#42) +- `88dcebc` docs: record length-only Sense password policy (#42) +- `245d38d` docs: create task 42 acceptance archive (#42) diff --git a/wiki-docs.json b/wiki-docs.json index e3571c5..7865684 100644 --- a/wiki-docs.json +++ b/wiki-docs.json @@ -119,6 +119,10 @@ { "page": "Task-40-Sense全模式密码最短6位", "path": "docs/task/40-Sense全模式密码最短6位.md" + }, + { + "page": "Task-42-Sense密码策略仅限制最短6位", + "path": "docs/task/42-Sense密码策略仅限制最短6位.md" } ] }