WeKan 用户管理 REST API 实战指南:注册、创建、查询、禁用与删除
2026/9/13 21:11:35 网站建设 项目流程

WeKan 用户管理 REST API 实战指南:注册、创建、查询、禁用与删除

【免费下载链接】wekanThe Open Source kanban, built with Meteor. GitHub issues/PRs are only for FLOSS Developers, not for support, support is at https://wekan.fi/commercial-support/ . PR source translation to imports/i18n/data/en.i18n.json, other translations at https://app.transifex.com/wekan/wekan项目地址: https://gitcode.com/GitHub_Trending/we/wekan

本指南以 WeKan 官方 API 文档(docs/API/User.md)为主线,系统讲解用户生命周期管理的全部 REST 端点:从无需认证的用户自助注册、管理员创建/删除用户、查询用户信息与用户列表,到通过 PUT 动态禁用/启用登录。阅读后你将能够独立编写 curl 脚本或集成代码,完成对 WeKan 实例用户的完整增删改查,并理解每个端点背后的权限模型与安全边界。

环境前提与认证模型

开启 REST API

WeKan 的 REST API 由WITH_API环境变量控制。从 server/apiMiddleware.js 的 API 网关逻辑可见:所有/api前缀请求在WITH_API !== 'true'时直接返回 HTTP 403 纯文本说明,而不是重定向——这意味着 API 关闭时,导出 PDF、Excel、CSV 等依赖/api/...地址的功能同样不可用。因此使用本指南前,请先确认实例以WITH_API=true启动。

# 示例:以环境变量方式启动 WITH_API=true node main.js

Token 获取与传递

文档反复强调:"You will need to provide thetokenfor any of the authenticated methods."。Token 的获取方式有两种:

  1. 首次登录即返回 tokenPOST /users/register在成功创建账户时直接返回tokentokenExpires,无需再次登录。
  2. 显式登录:调用POST /users/login,成功后返回同样的id / token / tokenExpires结构(实现在 server/apiAuthRoutes.js)。

Token 通过Authorization: Bearer <token>请求头携带。底层解析逻辑位于 server/apiMiddleware.js:中间件先读取Authorization: Bearer xxx请求头,若不存在则回退到access_token查询参数;随后用Accounts._hashLoginToken对 token 做哈希,在services.resume.loginTokens.hashedToken中匹配用户,匹配成功则把用户 id 写入req.userId

管理员判定

文档在 User Information 与 User List 两节特别注明:"Only the admin user (the first user) can call the REST API." 源码印证了这一规则:server/authentication.js 中Authentication.checkUserId只做两件事——未携带 token 抛 401Unauthorized;token 对应用户不是isAdmin: true时抛 403Forbidden。因此:

  • 第一个注册成功的用户是站点管理员(isAdmin: true);
  • 所有标有 "Requires Admin Auth" 的端点,都必须使用管理员账号的 token。

另外注意 server/apiAuthRoutes.js 的登录节流:REST 登录路径不经过 DDP 层的 accounts-lockout 钩子,因此单独实现了按客户端地址计数的失败节流(REST_LOGIN_MAX_FAILURESREST_LOGIN_FAILURE_WINDOW_SECONDSREST_LOGIN_LOCKOUT_SECONDS三个环境变量可调),连续失败会返回 429 并携带Retry-After响应头。这对集成脚本设计重试逻辑很重要。

用户自助注册:POST /users/register

该端点无需认证,用于公开注册。

URLRequires AuthHTTP Method
/users/registernoPOST

Payload

ArgumentExampleRequiredDescription
usernamemyusernameRequired用户名
passwordmy$up3erP@ssw0rdRequired密码
emailmy@email.comRequired邮箱

示例调用 —— Form Data

curl http://localhost:3000/users/register \ -d "username=myusername&password=mypassword&email=my@email.com"

示例调用 —— JSON

curl -H "Content-type:application/json" \ http://localhost:3000/users/register \ -d '{ "username": "myusername", "password": "mypassword", "email": "my@email.com" }'

响应

{ "id": "user id", "token": "string", "tokenExpires": "ISO encoded date string" }

响应示例

{ "id": "XQMZgynx9M79qTtQc", "token": "ExMp2s9ML1JNp_l11sIfINPT3wykZ1SsVwg-cnxKdc8", "tokenExpires": "2017-12-15T00:47:26.303Z" }

源码级解读

注册处理器位于 server/apiAuthRoutes.js,其关键行为包括:

  • 参数校验:使用check(options, {...})校验请求体,usernameemail为可选项、password必填(Match.Optional+String类型约束)。
  • 受"禁用注册"开关约束:这是本项目近期修复的一个安全漏洞(SignupBleed)。旧实现读取的forbidClientAccountCreation在 WeKan 中从未被设置,导致管理后台关闭注册后该端点依旧开放。现在处理器改为读取ReactiveCache.getCurrentSetting()中的disableRegistration字段,为true时记录安全日志(authz.register分类)并返回HTTP 403。对应回归测试见 tests/restRegisterRespectsSetting.test.cjs。
  • 创建与签发 token:调用Accounts.createUserAsync(userOptions)建号,随后Accounts._generateStampedLoginToken()生成登录令牌、Accounts._insertLoginToken写入用户文档,并计算Accounts._tokenExpiration作为过期时间——这就是响应中tokentokenExpires的来源。
  • 创建限速:server/models/users.js 中注册了 DDP 方法级限速:每个客户端地址每 60 秒最多 10 次createUser调用,防止注册接口被批量轰炸。

管理员创建用户:POST /api/users

URLRequires Admin AuthHTTP Method
/api/usersyesPOST

Payload

ArgumentExampleRequiredDescription
usernamemyusernameRequired用户名
passwordmy$up3erP@ssw0rdRequired密码
emailmy@email.comRequired邮箱

示例调用 —— Form Data

curl -H "Authorization: Bearer a6DM_gOPRwBdynfXaGBaiiEwTiAuigR_Fj_81QmNpnf" \ -X POST \ http://localhost:3000/api/users \ -d "username=myusername&password=mypassword&email=my@email.com"

示例调用 —— JSON

curl -H "Authorization: Bearer a6DM_gOPRwBdynfXaGBaiiEwTiAuigR_Fj_81QmNpnf" \ -H "Content-type:application/json" \ -X POST \ http://localhost:3000/api/users \ -d '{ "username": "myusername", "password": "mypassword", "email": "my@email.com" }'

响应

返回新用户的 id:

{ "_id": "user id" }

响应示例

{ "_id": "EnhMbvxh65Hr7YvtG" }

源码级解读

处理器位于 server/models/users.js:

  • 首先await Authentication.checkUserId(req.userId)确认调用者是管理员;
  • 然后调用Accounts.createUser({ username, email, password, from: 'admin' })创建账户,from: 'admin'标记该账户由管理员后台创建;
  • 文档补充说明:该端点在自注册开启或关闭时都可用——因为它是管理员显式授权操作,不受disableRegistration设置影响,可作为企业内部"管理员代开账号"的标准通道。

管理员删除用户:DELETE /api/users/:id

重要提示:文档注明,在 issue #1289),不会清理该用户在卡片、评论中的历史引用,可能留下脏数据。若需求是"移除访问权限但保留历史记录",更推荐使用下方的disableLogin禁用方式,或在管理界面使用匿名化(anonymize)替代方案(见Meteor.methods.anonymizeUser,server/models/users.js)。

URLRequires Admin AuthHTTP Method
/api/users/:idyesDELETE

参数

ArgumentExampleRequiredDescription
idBsNr28znDkG8aeo7WRequired要删除的用户 id

示例调用

curl -H "Authorization: Bearer a6DM_gOPRwBdynfXaGBaiiEwTiAuigR_Fj_81QmNpnf" \ -X DELETE \ http://localhost:3000/api/users/EnhMbvxh65Hr7YvtG

响应

返回被删除用户的 id:

{ "_id": "EnhMbvxh65Hr7YvtG" }

源码级解读与测试验证

该端点的行为被 tests/restUserDelete.test.cjs 用独立的 Node 脚本完整固定,值得关注:

  • 先鉴权后删除Authentication.checkUserId抛错时根本不会触达removeAsync(测试第 155-174 行验证非管理员返回 403);
  • 删除计数校验removeAsync返回 0 表示用户不存在,返回HTTP 404而非静默成功;返回值异常(如 2)则抛错转 500,避免误报(测试第 108-136 行);
  • 数据库故障同样被捕获为 500,而不会让进程崩溃。

查询用户信息:GET /api/users/:id

URLRequires Admin AuthHTTP Method
/api/users/:idyesGET

示例调用

curl -H "Authorization: Bearer a6DM_gOPRwBdynfXaGBaiiEwTiAuigR_Fj_81QmNpnf" \ http://localhost:3000/api/users/XQMZgynx9M79qTtQc

响应示例

{ "_id": "XQMZgynx9M79qTtQc", "createdAt": "2017-09-13T06:45:53.127Z", "services": { "password": { "bcrypt": "$2a$10$CRZrpT4x.VpG2FdJxR3rN.9m0NbQb0OPsSPBDAZukggxrskMtWA8." }, "email": { "verificationTokens": [ { "token": "8rzwpq_So2PVYHVSfrcc5f5QZnuV2wEtu7QRQGwOJx8", "address": "my@email.com", "when": "2017-09-13T06:45:53.157Z" } ] }, "resume": { "loginTokens": [ { "when": "2017-09-13T06:45:53.265Z", "hashedToken": "CY/PWeDa3fAkl+k94+GWzCtpB5nPcVxLzzzjXs4kI3A=" }, { "when": "2017-09-16T06:06:19.741Z", "hashedToken": "74MQNXfsgjkItx/gpgPb29Y0MSNAvBrsnSGQmr4YGvQ=" } ] } }, "username": "john", "emails": [ { "address": "my@email.com", "verified": false } ], "isAdmin": true, "profile": {} }

源码级解读

处理器位于 server/models/users.js:

  • 支持按用户名查询req.params.userId首先按_id查,查不到则回退按username查(代码中ReactiveCache.getUser({ username: id })),所以 URL 中的 id 位置实际上可以传用户名;
  • 附带成员关系:响应会额外携带boards数组,列出该用户在所有看板上的成员角色(boardId+ 各权限标志),便于调用方判断用户在看板体系中的权限;
  • 机密字段剥离:由于历史漏洞 GHSA-6qpx-x7vr-p9w6(管理员 API 曾泄露services.password.bcrypt密码哈希与全部会话令牌),现在所有管理端用户响应都会经过withoutSecrets()过滤(server/models/users.js),删除servicessessionData子树。注意:上文响应示例是旧版文档的原始输出,当前仓库已不再返回services字段。

查询用户列表:GET /api/users

URLRequires Admin AuthHTTP Method
/api/usersyesGET

示例调用

curl -H "Authorization: Bearer cwUZ3ZsTaE6ni2R3ppSkYd-KrDvxsLcBIkSVfOCfIkA" \ http://localhost:3000/api/users

响应

[ { "_id": "user id", "username": "string" } ]

响应示例

[ { "_id": "XQMZgynx9M79qTtQc", "username": "admin" }, { "_id": "vy4WYj7k7NBhf3AFc", "username": "john" } ]

源码级解读

处理器位于 server/models/users.js。它通过Authentication.checkUserId鉴权后,用Meteor.users.find({}, { fields: { _id: 1, username: 1 } })投影只取_idusername两个字段,再逐条映射输出。因此该端点永远不会返回邮箱、密码哈希等敏感信息,适合作为"用户名/id 对照表"用于后续批量操作(例如拿到 id 后逐一 GET 详情或 PUT 禁用)。

查询当前登录用户:GET /api/user

URLRequires AuthHTTP Method
/api/useryesGET

与上面的管理员端点不同,此端点只需登录、不需管理员,返回当前 token 对应用户自身的信息。处理器位于 server/models/users.js:使用Authentication.checkLoggedIn(req.userId)仅校验已登录,然后删除services字段、附加自己的看板成员列表后返回。

示例调用

curl -H "Authorization: Bearer a6DM_gOPRwBdynfXaGBaiiEwTiAuigR_Fj_81QmNpnf" \ http://localhost:3000/api/user

响应示例

{ "_id": "vy4WYj7k7NBhf3AFc", "createdAt": "2017-09-16T05:51:30.339Z", "username": "john", "emails": [ { "address": "me@mail.com", "verified": false } ], "profile": {} }

禁用与启用用户:PUT /api/users/:id

这是不删除数据、仅冻结账号的标准手段:禁用后用户无法登录,且其全部登录令牌会被清除;启用后恢复。

URLRequires Admin AuthHTTP Method
/api/users/:idyesPUT

禁用用户

curl -H "Authorization: Bearer t7iYB86mXoLfP_XsMegxF41oKT7iiA9lDYiKVtXcctl" \ -H "Content-type:application/json" \ -X PUT \ http://localhost:3000/api/users/ztKvBTzCqmyJ77on8 \ -d '{ "action": "disableLogin" }'

启用用户

curl -H "Authorization: Bearer t7iYB86mXoLfP_XsMegxF41oKT7iiA9lDYiKVtXcctl" \ -H "Content-type:application/json" \ -X PUT \ http://localhost:3000/api/users/ztKvBTzCqmyJ77on8 \ -d '{ "action": "enableLogin" }'

源码级解读

处理器位于 server/models/users.js,动作由请求体中的action字段区分:

  • disableLogin:对目标用户$set: { loginDisabled: true, 'services.resume.loginTokens': '' }—— 既打上禁用标记,又清空所有会话令牌(文档注释明确说明 "his login tokens are purged"),实现立即强制下线。源码同时防止管理员禁用自己(id !== req.userId条件)。
  • enableLogin$set: { loginDisabled: '' }清除禁用标记。
  • 配合 server/authentication.js 中Accounts.validateLoginAttempt的钩子(return !user.loginDisabled),loginDisabled字段对所有登录方式(本地密码、LDAP、OIDC 等)统一生效。
  • 该端点同样接受额外动作takeOwnership(接管目标用户管理的看板),从源码可见它是"删除管理员"场景的配套操作,本指南不展开。

完整实战:管理员创建用户的四步流程

官方文档给出了一条端到端链路,这里保留原文步骤并补充注释:

1) 登录获取管理员 token

curl http://example.com/users/login \ -d "username=YOUR-USERNAME-HERE&password=YOUR-PASSWORD-HERE"

响应返回你的idtoken

"id":"YOUR-ID-HERE","token":"YOUR-TOKEN-HERE","tokenExpires":"2017-12-23T21:07:10.395Z"}

2) 创建用户(自注册开启或关闭时均可用)

curl -H "Authorization: Bearer YOUR-TOKEN-HERE" \ -H "Content-type:application/json" \ -X POST \ http://example.com/api/users \ -d '{ "username": "tester", "password": "tester", "email": "tester@example.com", "fromAdmin": "true" }'

响应返回新用户的 id:

{"id":"NEW-USER-ID-HERE"}

3) 用新用户 id 查询其详情

curl -H "Authorization: Bearer YOUR-TOKEN-HERE" \ http://example.com/api/users/NEW-USER-ID-HERE

4)(可选)冻结或删除

需要临时冻结时改用第 3 步的 token 执行 PUT{"action":"disableLogin"};确需永久删除再走 DELETE。整个流程中,token 只应来自第 1 步的管理员账号,否则所有管理端点都会返回 403。

常见问题与安全提醒

  • 401 vs 403:未携带或携带无效 token 时管理端点返回 401Unauthorized;token 有效但非管理员时返回 403Forbidden(见 server/authentication.js)。
  • 响应体不是直接可用的对象:当前源码中所有 API 处理器统一用sendJsonResult输出{ code: 200, data: {...} }结构(server/apiMiddleware.js),集成脚本需读取data字段;这与文档中旧版的裸对象示例存在差异,请以实际响应为准。
  • 注册开关联动POST /users/register受管理后台"禁用注册"设置约束,返回 403;而管理员POST /api/users不受影响。
  • 敏感数据最小化GET /api/users只返回_id/username,管理端详情接口会剥离servicessessionData,任何调用方都无法通过 REST API 获取密码哈希或会话令牌。
  • 删除需谨慎:DELETE 是硬删除且存在历史问题(issue #1289),生产环境优先考虑disableLogin禁用或匿名化方案。

代码即文档:深入模型层

文档结尾指引读者直接阅读模型源码:"In Wekan code" 一节指向 models/users.js(原文档相对链接../../models/users.js对应仓库根目录的该文件),其中定义了用户集合的完整 Schema 与各类帮助方法。与本文 REST 端点直接相关的服务端实现则位于:

  • server/models/users.js:/api/users系列全部 REST 处理器(列表、详情、创建、删除、PUT 禁用/启用)
  • server/apiAuthRoutes.js:/users/register/users/login/users/logout
  • server/apiMiddleware.js:Bearer token 解析、WITH_API网关、sendJsonResult响应封装
  • server/authentication.js:管理员鉴权与登录校验钩子
  • tests/restUserDelete.test.cjs 与 tests/restRegisterRespectsSetting.test.cjs:删除行为与注册开关的回归测试

对照阅读可确认:本文涉及的每个端点行为均有源码与测试双重印证,可放心用于实际集成开发。

【免费下载链接】wekanThe Open Source kanban, built with Meteor. GitHub issues/PRs are only for FLOSS Developers, not for support, support is at https://wekan.fi/commercial-support/ . PR source translation to imports/i18n/data/en.i18n.json, other translations at https://app.transifex.com/wekan/wekan项目地址: https://gitcode.com/GitHub_Trending/we/wekan

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

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询