news 2026/9/10 22:30:12

Harbor 用户生命周期实战:管理员在本地数据库(DB)模式下创建、删除与重建用户的完整验证指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Harbor 用户生命周期实战:管理员在本地数据库(DB)模式下创建、删除与重建用户的完整验证指南

Harbor 用户生命周期实战:管理员在本地数据库(DB)模式下创建、删除与重建用户的完整验证指南

【免费下载链接】harborAn open source trusted cloud native registry project that stores, signs, and scans content.项目地址: https://gitcode.com/GitHub_Trending/ha/harbor

导读

本文以 Harbor 官方用户管理测试用例 1-09 Admin User Create, Delete and Recreate a User (DB Mode) 为核心,系统讲解在 Harbor 使用本地数据库(DB 模式)认证时,管理员如何通过 UI 创建用户、删除用户,并利用相同用户名重新创建用户的全过程。你将掌握用户生命周期管理的完整操作步骤、docker login命令行验证方法,以及 Harbor 用户存储与"软删除 + 用户名改写"机制的源码级实现原理,可用于功能测试、验收与故障排查。


一、测试背景:为什么要在 DB 模式下验证用户管理

Harbor 支持多种认证模式,其中本地数据库模式(DB mode)表示用户账号由 Harbor 自身维护,登录时直接与 Harbor 数据库中的harbor_user表比对。在 src/common/const.go 中,该模式被定义为常量DBAuth = "db_auth"

本测试用例的目标是验证在 DB 模式下,管理员能否完整走通创建用户 → 用户登录与使用 → 删除用户 → 会话失效 → 重建同名用户的闭环流程,重点确认以下行为:

  • 新创建的用户可以正常登录 UI 与 Docker CLI;
  • 管理员删除用户后,该用户既有的 Web 会话立即失效(跳转回登录页),也无法再通过docker login认证;
  • 删除是可逆复用的——相同用户名可以再次被创建,但新建用户是全新的账号,不再拥有被删用户的任何项目;
  • 审计日志中会以"特殊编号"形式残留被删用户的信息,便于追溯。

该用例对应的完整测试步骤与预期结果记录于 tests/testcases/Group1-user-management/1-09-admin-create-delete-user.md。


二、测试环境准备

2.1 前提条件

执行本用例需要满足以下环境要求:

前提说明
运行中的 Harbor 实例已安装并可通过浏览器访问 Harbor UI
DB 认证模式Harbor 配置为auth_mode: db_auth(本地数据库认证)
Linux 主机已安装 Docker CLI(Docker 客户端)用于命令行登录验证
管理员账号使用内置的admin账号(数据库种子数据中user_id=1的系统管理员)

2.2 DB 模式确认方式

DB 模式在 Harbor 部署配置文件harbor.yml中通过auth_mode字段指定:

auth_mode: db_auth

部署时由make/prepare根据 harbor.yml.tmpl 模板生成实际配置。注意,该模式的创建权限还受self_registration(自助注册)开关影响:在 src/server/v2.0/handler/user.go 的requireCreatable逻辑中,创建用户时若开启了自助注册,普通登录用户也可在 UI 上注册;而管理员创建用户始终被允许(requireCreatable中当self_registration=false时仅校验系统级Create/User权限)。

内置admin账号与anonymous账号由数据库初始迁移脚本 make/migrations/postgresql/0001_initial_schema.up.sql 写入,其中adminsysadmin_flag=trueuser_id=1,且在用户列表中默认被隐藏(src/pkg/user/manager.go 通过user_id__gt = 1过滤默认管理员)。


三、完整测试步骤(15 步实操)

以下步骤为原测试用例的完整操作序列,建议在测试时严格按序执行。

Step 1:管理员登录 UI

使用内置管理员账号登录 Harbor Web 控制台。登录后进入顶部导航的Administration → Users(系统管理 → 用户)页面,可查看、创建、删除本地用户。

Step 2:管理员创建用户

在 Users 管理页面点击New User,填写用户名(Username)、邮箱(Email)、全名(Realname)、备注(Comment)与密码(Password),提交创建。

密码必须满足 Harbor 的密码强度策略:长度 8~128 位,且同时包含至少 1 个大写字母、1 个小写字母与 1 个数字。该规则实现在 src/server/v2.0/handler/user.go 的requireValidSecret函数中,任何不满足要求的密码都会在创建或改密时被拒绝:

if len(in) >= 8 && len(in) <= 128 && hasLower.MatchString(in) && hasUpper.MatchString(in) && hasNumber.MatchString(in) { return nil }

同时,用户名与全名不能包含非法字符(,"~#%$,见 src/common/const.go 的IllegalCharsInUsername),用户名、邮箱不能为空,邮箱需符合格式校验,备注长度不超过 30 个字符(validateUserProfile)。

Step 3:在另一个浏览器登录新用户

使用与管理员不同的浏览器(模拟独立的会话环境,避免共享 Cookie),用 Step 2 创建的账号密码登录 Harbor UI,应能成功登录。

Step 4:新用户查看自己的账户设置

登录后点击右上角用户名进入Account Settings(账户设置),应能看到管理员在 Step 2 填写的邮箱、全名等信息与创建时的输入一致。

Step 5:新用户在 UI 中创建两个项目

新用户通过New Project创建两个项目(项目名需唯一)。普通用户创建项目时需要满足配额与命名规则要求,创建成功后项目所有者即为该用户。

Step 6:Docker CLI 验证用户可登录

在装有 Docker CLI 的 Linux 主机上执行:

docker login <harbor_host>

输入 Step 2 创建的用户名与密码。若 Harbor 未配置 HTTPS,需在 Docker 守护进程的/etc/docker/daemon.json中将 Harbor 地址加入insecure-registries。登录成功即代表该用户具备向 Harbor 推送/拉取镜像的凭证能力。

Step 7:管理员删除用户

回到管理员的浏览器,在Administration → Users列表中找到刚创建的用户,执行删除操作。

Step 8:验证被删用户的会话被强制登出

在 Step 3 使用的新用户浏览器中,点击页面上的任意链接(触发一次新的 HTTP 请求)。此时该用户的会话应立即失效,页面被重定向到登录页。

原理说明:Harbor 的认证安全上下文(src/common/security 下的local.SecurityContext)在每次请求时都会基于当前会话对应的用户记录构建。用户被删除后,其数据库记录被标记为deleted=true且用户名/邮箱被改写,后续请求无法再以该用户身份通过认证校验,因此会话表现为被强制登出。这也解释了为什么用例特别强调"点击任意链接"——需要触发一次真实请求才能观察到跳转。

Step 9:Docker CLI 验证被删用户无法登录

回到 Linux 主机,再次执行:

docker login <harbor_host>

使用被删除的用户名登录,应提示认证失败(unauthorized: authentication required),确认删除后该用户在客户端侧也无法继续使用。

Step 10:管理员重建同名用户

回到管理员浏览器,在New User使用与被删除用户完全相同的用户名再次创建用户(密码、邮箱等可重新设置)。此步骤应成功——这正是 Harbor 软删除机制设计的关键点(详见下文源码剖析)。

Step 11:在另一个浏览器登录重建用户

使用新的浏览器(或清除原浏览器 Cookie)以重建的用户登录,应成功登录。

Step 12:重建用户查看账户设置

进入Account Settings,确认看到的是本次重建时填写的资料,而不是被删除用户的旧资料。

Step 13:重建用户查看"我的项目"

进入My Projects页面,应看到项目列表为——虽然用户名相同,但被删用户在 Step 5 创建的两个项目不再属于新账号。

原理说明:项目通过owner_id(外键)关联harbor_user.user_id(见 make/migrations/postgresql/0001_initial_schema.up.sql)。重建用户的user_id是数据库自增的新值,与被删用户的user_id不同,因此历史项目不会自动转移给新账号。同时,删除用户时 Harbor 会先清理该用户在project_member表中的成员记录(见下文 Controller 层代码),确保成员关系一并解除。

Step 14:Docker CLI 验证重建用户可登录

执行:

docker login <harbor_host>

使用重建的用户名密码登录,应成功,确认同名重建后账号完整可用。

Step 15:管理员在日志中确认特殊用户编号

管理员从 UI 的Logs(日志)页面查看审计日志。由于被删除用户曾在 Step 5 创建过两个项目,日志中应出现两条项目创建记录,且记录关联的操作用户显示为带有特殊编号的形式(即被删用户的用户名被改写后残留的用户名#userID格式,详见下文)。

注意:日志显示的具体格式取决于审计记录对用户名的抓取时机,核心验证点是"能看到带编号的用户标识,而不是普通用户名"。


四、预期结果汇总

步骤预期结果
Step 3新用户成功登录 UI
Step 4新用户看到的账户设置与管理员录入一致
Step 5新用户成功创建两个项目
Step 6Docker CLI 登录成功
Step 8被删用户点击任意链接后跳转登录页,会话失效
Step 9Docker CLI 登录失败
Step 10管理员可重建同名用户
Step 11~13重建用户可登录,但不再拥有原用户的项目
Step 14Docker CLI 登录成功
Step 15日志中出现带特殊用户编号的项目创建记录

五、源码级原理剖析:软删除与同名重建的关键机制

5.1 用户数据模型

用户实体定义在 src/common/models/user.go,核心字段包括UserIDUsernameEmailPasswordPasswordVersionSaltDeletedSysAdminFlag等。

对应的数据库表harbor_user由初始迁移脚本 make/migrations/postgresql/0001_initial_schema.up.sql 创建,其关键设计是:

create table harbor_user ( user_id SERIAL PRIMARY KEY NOT NULL, username varchar(255), email varchar(255), ... deleted boolean DEFAULT false NOT NULL, ... UNIQUE (username), UNIQUE (email) );

其中usernameemail均建有UNIQUE 唯一约束。这意味着同一时刻数据库中不允许存在两条相同的用户名——要让"删除后重建同名用户"成为可能,删除操作就不能简单地物理删除记录,否则唯一约束本身并不妨碍重建(删除后约束自然释放);真正的难点在于 Harbor 采用了软删除策略,删除的记录仍然留在表中。

5.2 删除用户的实现:软删除 + 用户名改写

Manager 层的删除实现位于 src/pkg/user/manager.go:

func (m *manager) Delete(ctx context.Context, id int) error { u, err := m.Get(ctx, id) if err != nil { return err } u.Username = lib.Truncate(u.Username, fmt.Sprintf("#%d", u.UserID), 255) u.Email = lib.Truncate(u.Email, fmt.Sprintf("#%d", u.UserID), 255) u.Deleted = true return m.dao.Update(ctx, u, "username", "email", "deleted") }

关键点如下:

  1. 不是物理删除:删除只把deleted标记置为true,保留记录用于审计追溯;
  2. 改写用户名与邮箱:将用户名改写为原名#userID(邮箱同理),从而释放username/email的唯一约束,使得后续可以用相同用户名新建记录而不产生唯一键冲突——这正是 Step 10 重建成功的底层原因;
  3. DAO 层更新:通过 src/pkg/user/dao/dao.go 的Update仅更新指定列。

需要说明的是,DAO 层接口中虽然也定义了物理删除Delete(ctx, userID)(src/pkg/user/dao/dao.go),但 Manager 层面向用户删除流程使用的是上述软删除路径。

此外,若启用了 GDPR 合规设置,Harbor 还提供DeleteGDPR实现(src/pkg/user/manager.go),它进一步将用户名、邮箱、全名替换为crc32校验和#userID形式,以抹除个人可识别信息(PII)。

5.3 Controller 层的级联清理

删除请求最终进入 src/controller/user/controller.go 的Delete,它会在标记删除之前完成级联清理:

  1. 通过memberMgr.DeleteMemberByUserID删除该用户在所有项目中的成员关系(这正是 Step 13 中"新用户不再拥有项目"的辅助原因之一);
  2. 在 OIDC 认证模式下,同步删除该用户的 OIDC 元数据;
  3. 若配置了 GDPR 审计日志,则触发 GDPR 审计任务;
  4. 最后根据gdprSetting.DeleteUser决定走DeleteGDPR还是普通Delete

5.4 API 层的权限与合法性校验

V2.0 REST API 的创建与删除处理器位于 src/server/v2.0/handler/user.go:

  • 创建用户CreateUser(L80-L104):先经requireCreatable校验必须是 DB 认证模式且具备系统级创建权限,再校验密码强度与用户资料合法性,最后调用ctl.Create落库;
  • 删除用户DeleteUser(L183-L193):经requireDeletable(L394-L402)校验——管理员不能删除自己,也不能删除user_id=1的内置管理员,否则返回403 Forbidden

5.5 创建用户的密码加密

创建用户时,Manager 层通过injectPasswd(src/pkg/user/manager.go)为密码生成随机盐值,并使用PBKDF2-HMAC-SHA256算法(高迭代次数)加密存储,同时记录password_version;登录校验MatchLocalPassword(src/pkg/user/manager.go)是版本感知的,历史版本使用 SHA1/SHA256 哈希的存量用户仍可正常认证。


六、日志验证的补充说明(Step 15)

Step 15 是容易被忽略的审计重点:管理员在 Dashboard 的日志中应看到两条项目创建记录(对应被删用户在 Step 5 创建的两个项目),且记录中操作用户显示为带编号的特殊形式。

这与 5.2 节描述的软删除机制直接相关:被删用户的用户名在删除时已被改写为用户名#userID格式,项目创建日志(在删除前写入)保留的是当时的用户名信息。通过该特殊编号可以追溯到被删用户的user_id,这是 Harbor 软删除保留记录用于审计的直接体现。


七、常见问题排查(实战补充)

原用例的 "Possible Problems" 为 None,但基于源码约束,实际执行中可能出现以下情况,供排查参考:

现象原因处理
创建用户提示密码不合法密码不满足 8~128 位且含大小写字母与数字按 requireValidSecret 规则修改密码
删除时提示 "User cannot be deleted"试图删除自己或内置adminuser_id=1换用其他管理员账号执行删除
非 DB 模式下创建用户被拒requireCreatable限制仅 DB 模式允许创建本地用户在 LDAP/OIDC 模式下改用认证目录管理用户
重建用户后看不到旧项目owner_id关联的是旧user_id,且删除时已清理项目成员关系属于预期行为,将旧项目授权给新账号需重新添加成员
登录被强制登出用户记录已标记deleted=true属于预期行为,管理员可重建同名账号

八、结语

通过本用例可以确认,Harbor 在 DB 模式下提供了完整、安全的用户生命周期管理能力:创建时强制密码强度与字段合法性校验,删除时采用"软删除 + 用户名/邮箱改写"策略释放唯一约束,从而允许同名用户重建,同时保证旧项目归属与成员关系不随用户名转移,且被删用户的所有会话立即失效。掌握这套流程与背后的 src/pkg/user 源码实现,对于 Harbor 的用户验收测试、日常运维与审计追溯都极具实战价值。

延伸阅读:用户管理相关的更多测试用例可参考 tests/testcases/Group1-user-management 目录;用户相关 REST API 定义见 api/v2.0/swagger.yaml 中/users相关章节;用户管理 API 的实现入口为 src/server/v2.0/handler/user.go。

【免费下载链接】harborAn open source trusted cloud native registry project that stores, signs, and scans content.项目地址: https://gitcode.com/GitHub_Trending/ha/harbor

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/10 22:27:57

留个神!不是每款 AI 都能用来写学术论文,2026 高校认可工具精选

每年毕业季&#xff0c;无数同学深陷论文难题&#xff1a;开题毫无思路、搭建框架耗费数日、初稿逻辑松散、查重标红泛滥、AI检测超标、格式反复被导师驳回。面对繁重的写作任务&#xff0c;许多学生开始依赖通用型AI工具&#xff0c;但市面上大多数AI平台存在严重短板。它们往…

作者头像 李华
网站建设 2026/9/10 22:27:36

SpringBoot打印店预约系统:技术实现与优化

1. 项目背景与核心价值打印店作为高校和办公区的高频服务场所&#xff0c;传统的人工登记模式存在三大痛点&#xff1a;高峰期排队耗时、订单状态不透明、文件安全管理薄弱。这套基于SpringBoot的预约取件系统&#xff0c;正是为解决这些实际问题而设计的轻量级解决方案。我在实…

作者头像 李华
网站建设 2026/9/10 22:27:22

Python与Milvus构建高效向量搜索系统指南

1. 为什么选择PythonMilvus这个技术组合&#xff1f;Milvus作为一款开源的向量数据库&#xff0c;在处理非结构化数据时展现出独特优势。而Python凭借其简洁语法和丰富生态&#xff0c;成为AI领域事实上的标准语言。这两者的结合&#xff0c;为开发者提供了从数据预处理到向量存…

作者头像 李华
网站建设 2026/9/10 22:26:19

无线传感器网络LEACH协议优化与DBN能效提升方案

1. 项目概述&#xff1a;无线传感器网络中的智能优化挑战在物联网和工业4.0时代&#xff0c;无线传感器网络(WSN)作为物理世界与数字世界的桥梁&#xff0c;其能效和成本优化一直是研究热点。传统LEACH协议虽然解决了集群头选择的基本问题&#xff0c;但在动态环境和复杂应用场…

作者头像 李华
网站建设 2026/9/10 22:25:25

实验动物预约订购系统:数字化管理解决方案

1. 实验动物预约订购系统概述实验室动物管理一直是科研机构面临的重要挑战。传统的人工登记方式效率低下&#xff0c;容易出错&#xff0c;特别是在多课题组共用动物房的情况下。我们团队开发的这套实验动物预约订购系统&#xff0c;正是为了解决这些痛点而生。这个系统本质上是…

作者头像 李华