☰
OctoPrint JS Client Library 访问控制模块(OctoPrintClient.access)完整指南
2026/9/25 5:37:11 网站建设 项目流程
  • 物联网
  • 后端

【免费下载链接】OctoPrint

OctoPrint is the snappy web interface for your 3D printer!

项目地址:https://gitcode.com/gh_mirrors/oc/OctoPrint
点击查看免费下载

导读

本文围绕 OctoPrint JavaScript Client Library 的访问控制(access)组件展开,系统讲解如何通过OctoPrintClient.access.permissions、OctoPrintClient.access.users与OctoPrintClient.access.groups三个子模块,在前端脚本或第三方客户端中完成权限查询、用户与用户组管理、密码与 API Key 维护、用户个性化设置读写等操作。读完本文,你将掌握 access 组件全部 API 方法及参数语义、底层 REST 端点映射、权限校验机制与常见错误处理,并能在自己的 OctoPrint 插件或外部客户端中直接落地使用。

组件定位与前置条件

access组件是 OctoPrint JS Client Library 中与「访问控制」REST API 对应的客户端封装。组件对应的源文档为 docs/jsclientlib/access.rst,其底层 HTTP 端点定义于 docs/api/access.rst,服务端实现位于 src/octoprint/server/api/access.py。

权限前提

文档开头即给出重要提示:本组件的大多数方法要求调用方持有的 API Token(X-Api-Key)或浏览器会话具备管理员权限,或者该会话恰好对应待操作的用户本身;部分方法则严格需要管理员权限。具体到每个方法,本文会在相应小节标注权限要求。

从源码看,权限校验在服务端通过装饰器强制执行。以 src/octoprint/server/api/access.py 为例:

  • 用户与用户组的大部分写操作使用@Permissions.ADMIN.require(403),非管理员直接返回 403;
  • 写操作(POST / PUT / DELETE)额外叠加@require_credentials_checked_recently,即要求“凭据已在近期验证过”(recent credentials check),防止借用长期有效的会话进行敏感操作;
  • 读取用户记录、修改密码、读写个人设置等接口则采用“当前用户等于目标用户,或拥有 ADMIN 权限”二选一的判定逻辑。

权限对象模型位于 src/octoprint/access/permissions.py:OctoPrintPermission通过as_dict()暴露key、name、dangerous、default_groups、description与needs字段;PermissionsMetaClass将注册的权限统一收集到Permissions.permissions字典,并支持Permissions.all()与Permissions.filter()遍历。/api/access/permissions端点正是用Permissions.all()枚举后逐个as_dict()输出(见 src/octoprint/server/api/access.py 的get_permissions)。

引入方式

access属于按需加载的组件。按 docs/jsclientlib/index.rst 的说明,可以通过 webassets 一次性引入完整客户端:

{% assets "js_client" %}<script type="text/javascript" src="{{ ASSET_URL }}"></script>{% endassets %}

或只引入单个组件文件(注意不要遗漏base组件,其余所有组件都依赖它):

<script type="text/javascript" src="{{ url_for("static", filename="js/app/client/base.js") }}"></script> <script type="text/javascript" src="{{ url_for("static", filename="js/app/client/access.js") }}"></script>

同时必须保证 jQuery($)与 lodash(_)可用,组件源码 src/octoprint/static/js/app/client/access.js 依赖这两个全局对象:

<script src="{{ url_for("static", filename="js/lib/jquery/jquery.min.js") }}"></script> <script src="{{ url_for("static", filename="js/lib/lodash.min.js") }}"></script>

引入完成后,全局变量OctoPrint(OctoPrintClient的实例)即包含OctoPrint.access命名空间,其内部结构在 src/octoprint/static/js/app/client/access.js 末尾组装:

var OctoPrintAccessClient = function (base) { this.base = base; this.permissions = new OctoPrintAccessPermissionsClient(this); this.groups = new OctoPrintAccessGroupsClient(this); this.users = new OctoPrintAccessUsersClient(this); }; OctoPrintClient.registerComponent("access", OctoPrintAccessClient);

OctoPrintClient.registerComponent(见 src/octoprint/static/js/app/client/base.js)会把组件懒加载挂到客户端原型上,因此OctoPrint.access.permissions、OctoPrint.access.users、OctoPrint.access.groups均可直接访问。

OctoPrintClient.access.permissions:权限清单查询

permissions.list(opts)

获取系统内全部已注册权限的列表。

  • 参数opts:object,请求的附加选项(如自定义 headers、超时等);
  • 返回值:jQuery Promise,resolve 后携带权限列表响应。

实现位于 src/octoprint/static/js/app/client/access.js 的OctoPrintAccessPermissionsClient.prototype.list,内部仅调用this.base.get("api/access/permissions")。底层 REST 端点为GET /api/access/permissions(见 docs/api/access.rst 的 “List all permissions” 小节),服务端get_permissions返回形如{"permissions": [ ... ]}的 JSON,每个元素包含key、name、dangerous、default_groups、description、needs等字段(由 src/octoprint/access/permissions.py 的OctoPrintPermission.as_dict定义)。

典型用法:

OctoPrint.access.permissions.list() .done(function (response) { console.log(response.permissions); });

OctoPrintClient.access.users:用户管理

users子组件把用户相关的全部 REST 操作封装为 9 个方法,统一以api/access/users为基地址(见 src/octoprint/static/js/app/client/access.js 的OctoPrintAccessUsersClient)。下方列出方法签名、权限要求、底层端点与典型示例。

users.list(opts)

获取所有已注册用户的列表。

  • 需要管理员权限;
  • 底层端点:GET /api/access/users;
  • 服务端在 src/octoprint/server/api/access.py 的get_users中,对每个用户调用as_dict();若近期未验证过凭据,返回的用户记录中apikey会被置为null,这是刻意的安全行为。
OctoPrint.access.users.list() .done(function (response) { console.log(response.users); });

用户记录的数据结构由 src/octoprint/access/users.py 的User.as_dict定义,包含:name、active(布尔)、permissions(权限 key 列表)、groups(用户组 key 列表)、needs、apikey、settings、has_password。

users.get(name, opts)

获取指定用户的信息。

  • 参数name:string,用户名;
  • 底层端点:GET /api/access/users/<username>;
  • 权限:SETTINGS权限或登录身份即该用户本人(服务端逻辑见 src/octoprint/server/api/access.py 的get_user:current_user.get_name() == username or current_user.has_permission(Permissions.ADMIN));
  • 未知用户返回 404;无权限返回 403。
OctoPrint.access.users.get("user1") .done(function (user) { console.log(user.name, user.active, user.permissions); });

users.add(user, opts)

新增用户。

  • 需要管理员权限;
  • 参数user:object,新用户数据;
  • 底层端点:POST /api/access/users;
  • 客户端前置校验(见 src/octoprint/static/js/app/client/access.js):user.name与user.password必须存在,否则抛出InvalidArgumentError;
  • 客户端自动构造的请求体:name、password、groups(缺省为[])、permissions(缺省为[])、active(缺省为true,!!user.active强转布尔);
  • 服务端(add_user)要求请求体包含name、password、active,缺失时返回 400;用户名重复返回 409;用户名非法返回 400;
  • 成功时返回用户列表响应(与users.list相同结构)。
OctoPrint.access.users.add({ name: "newuser", password: "s3cr3t", active: true, groups: ["users"], permissions: [] }).done(function (response) { console.log(response.users); });

users.update(name, active, permissions, groups, opts)

更新既有用户。

  • 需要管理员权限;
  • 参数:name(string,用户名)、active(bool,新的激活状态)、permissions(list,权限 key 列表)、groups(list,用户组 key 列表)、opts(object);
  • 底层端点:PUT /api/access/users/<username>,客户端通过putJson提交{active: !!active, groups: groups, permissions: permissions};
  • 服务端update_user按请求体中出现的字段,分别调用change_user_groups、change_user_permissions、change_user_activation(见 src/octoprint/server/api/access.py);
  • 未知用户返回 404。

兼容性说明(重要):源码中保留了对旧参数顺序(name, active, admin, permissions, groups, opts)的兼容逻辑——当第三个参数permissions的类型是 boolean 时,会将其视为旧的admin标志,把所有参数左移一位并打印弃用警告:

if (typeof permissions == "boolean") { // old parameter order: name, active, *admin*, permissions, groups, opts console.log( "Calling OctoPrint.access.users.update with admin flag is deprecated and will be removed in OctoPrint 3.0.0. Use permissions or groups instead." ); permissions = groups; groups = opts; opts = arguments.length >= 6 ? arguments[5] : {}; }

因此,应始终使用新的五参数形式,不要依赖旧的 admin 布尔标志。

OctoPrint.access.users.update("newuser", true, ["ADMIN"], ["admins"]) .done(function (response) { /* ... */ });

users.delete(name, opts)

删除既有用户。

  • 需要管理员权限;
  • 底层端点:DELETE /api/access/users/<username>;
  • 服务端remove_user中,若目标用户即当前登录用户,返回 400(“You cannot delete yourself”);未知用户返回 404;
  • 成功时返回用户列表响应。
OctoPrint.access.users.delete("newuser") .done(function (response) { /* ... */ });

users.changePassword(name, password, oldpw, opts)

修改指定用户的密码。

  • 参数:name(string)、password(string,新密码)、oldpw(string,旧密码,可选但大多数情况下必需)、opts(object);
  • 底层端点:PUT /api/access/users/<username>/password;
  • 客户端实现有一个便捷行为:若第三个参数传入的是 object(即调用者省略了oldpw直接传opts),会自动把参数移位:if (_.isObject(oldpw)) { opts = oldpw; oldpw = undefined; };
  • 请求体为{"password": newPassword},仅在提供oldpw时才附加"current": oldpw;
  • 服务端规则(见 docs/api/access.rst 与change_password_for_user):拥有SETTINGS权限,或登录身份即目标用户;没有管理员权限时,请求体必须包含current(当前密码),且服务端会校验其正确性;若current被提供,即使调用方有管理员权限也会一并校验;
  • 典型错误码:400(缺password或必需的current)、403(无权限 / 非本人 / 凭据未近期验证 / 当前密码不匹配)、404(未知用户)。
// 用户本人修改自己的密码 OctoPrint.access.users.changePassword("user1", "newpass", "oldpass"); // 管理员为他人改密(不提供旧密码) OctoPrint.access.users.changePassword("user2", "newpass");

users.generateApiKey(name, opts)

为用户生成(重置)新的个人 API Key。

  • 底层端点:POST /api/access/users/<username>/apikey;
  • 权限:SETTINGS权限或登录身份即目标用户,且要求近期凭据校验(服务端generate_apikey_for_user);
  • 无需请求体;响应 JSON 中通过apikey属性返回新生成的 key(jsonify({"apikey": apikey}));
  • 生成逻辑在 src/octoprint/access/users.py 的generate_api_key。
OctoPrint.access.users.generateApiKey("user1") .done(function (response) { console.log("New API key:", response.apikey); });

users.resetApiKey(name, opts)

将用户的个人 API Key 重置为未设置状态。

  • 底层端点:DELETE /api/access/users/<username>/apikey;
  • 权限同上:SETTINGS权限或登录身份即目标用户,且要求近期凭据校验;
  • 成功后返回SUCCESS(204 语义),对应服务端delete_apikey_for_user调用的delete_api_key(见 src/octoprint/access/users.py)。
OctoPrint.access.users.resetApiKey("user1");

users.getSettings(name, opts)

获取指定用户的个人设置。

  • 底层端点:GET /api/access/users/<username>/settings;
  • 权限:SETTINGS权限或登录身份即目标用户(服务端get_settings_for_user返回userManager.get_all_user_settings(username));
  • 未知用户返回 404,无权限返回 403;
  • 返回的 JSON 对象即该用户的个性化设置(可能为空对象)。
OctoPrint.access.users.getSettings("user1") .done(function (settings) { /* ... */ });

users.saveSettings(name, settings, opts)

保存/更新指定用户的个人设置。

  • 参数settings:object,允许只传部分设置,服务端会将其与现有设置合并(merge),而非整体覆盖;
  • 底层端点:PATCH /api/access/users/<username>/settings(PATCH 语义天然支持部分更新);
  • 客户端通过patchJson提交,settings = settings || {}保证空对象合法;
  • 权限:SETTINGS权限或登录身份即目标用户;当操作者是管理员(非本人)时,服务端要求近期凭据校验;
  • 成功后返回SUCCESS。
OctoPrint.access.users.saveSettings("user1", { theme: "dark" }) .done(function () { /* 已合并保存 */ });

OctoPrintClient.access.groups:用户组管理

groups子组件对应api/access/groups端点(见 src/octoprint/static/js/app/client/access.js 的OctoPrintAccessGroupsClient)。用户组(group)用于批量授予权限:组内可包含权限列表、子组(subgroups)以及是否作为新用户默认组(default)。服务端模型在 src/octoprint/access/groups.py,内置了admin、users、guest、readonly等默认组(_init_defaults),其中users组默认对新建用户生效。

groups.list(opts)

获取所有已注册用户组的列表。

  • 底层端点:GET /api/access/groups,返回{"groups": [ ... ]};
  • 服务端get_groups对groupManager.groups逐个调用as_dict();
  • 权限:SETTINGS权限(见 docs/api/access.rst)。
OctoPrint.access.groups.list() .done(function (response) { console.log(response.groups); });

groups.get(key, opts)

获取指定用户组的信息。

  • 参数key:string,用户组 ID(注意是key而非显示名称);
  • 底层端点:GET /api/access/groups/<key>;
  • 服务端get_group通过groupManager.find_group(key)查找,未知组返回 404;
  • 客户端前置校验:key必须设置,否则抛出InvalidArgumentError。
OctoPrint.access.groups.get("admins") .done(function (group) { console.log(group); });

groups.add(group, opts)

新增用户组。

  • 需要管理员权限;
  • 参数group:object,要求至少包含key与name;还支持description、permissions、subgroups以及default布尔标志;
  • 客户端前置校验:group.key与group.name缺一不可,否则抛出InvalidArgumentError;
  • 请求体字段(见客户端add实现)与 REST 数据模型完全对应(docs/api/access.rst 的 “Group registration request” 表):
字段必填类型说明
key是string用户组标识符
name是string用户组显示名称
description否string可读描述,缺省为空串
permissions是string 列表分配给该组的权限 key 列表
subgroups否string 列表作为子组的用户组 key 列表
default否boolean是否将新用户默认加入该组(缺省 false)
  • 服务端add_group:缺少key/name/permissions/subgroups任一字段返回 400;组 key 已存在或存在循环子组引用(CyclicSubgroupReference)返回 409;
  • 成功时返回组列表响应。
OctoPrint.access.groups.add({ key: "operators", name: "Operators", description: "Machine operators", permissions: ["PRINT", "MONITOR_TERMINAL"], subgroups: ["users"], default: false }).done(function (response) { /* ... */ });

groups.update(group, opts)

更新既有用户组,通过group.key标识目标组。

  • 需要管理员权限;
  • 参数group:object,必须包含key;
  • 只会更新以下字段:description、permissions、subgroups、default(key与name不参与更新);
  • 客户端在组装请求体时,description若未在group中定义则置为空串(group.hasOwnProperty("description") ? group.description : ""),permissions、subgroups、default原样传递;
  • 底层端点:PUT /api/access/groups/<key>;
  • 服务端update_group:default字段按valid_boolean_trues解析为布尔;组不可修改(GroupCantBeChanged,如内置组)返回 403;未知组返回 404;循环子组引用返回 409;
  • 成功时返回组列表响应。
OctoPrint.access.groups.update({ key: "operators", description: "Machine operators (updated)", permissions: ["PRINT", "MONITOR_TERMINAL", "FILES_DOWNLOAD"], subgroups: ["users"], default: false }).done(function (response) { /* ... */ });

groups.delete(key, opts)

删除用户组。

  • 需要管理员权限;
  • 参数key:string,用户组 ID;
  • 底层端点:DELETE /api/access/groups/<key>;
  • 服务端remove_group:未知组返回 404;组不可移除(GroupUnremovable,如内置组)返回 403;
  • 成功时返回组列表响应。
OctoPrint.access.groups.delete("operators") .done(function (response) { /* ... */ });

底层请求机制与 Promise 使用要点

access组件的全部方法都基于 src/octoprint/static/js/app/client/base.js 提供的 HTTP 原语:

  • get(url, opts):GET,对应groups.list、users.get等;
  • postJson(url, data, opts):POST +Content-Type: application/json,请求体经JSON.stringify(undefined 值会被替换为 null),对应groups.add、users.add、users.generateApiKey;
  • putJson(url, data, opts):PUT + JSON,对应groups.update、users.update、users.changePassword;
  • patchJson(url, data, opts):PATCH + JSON,对应users.saveSettings;
  • delete(url, opts):DELETE,对应groups.delete、users.delete、users.resetApiKey。

所有方法都返回 jQuery Promise,可链式使用.done()、.fail()、.always()。鉴权头由getRequestHeaders统一注入:设置了OctoPrint.options.apikey时发送X-Api-Key;未设置时视为浏览器上下文,对非 GET/HEAD/OPTIONS 方法自动附加X-CSRF-Token(从csrf_tokencookie 读取,跨域请求除外)。因此,无论是通过OctoPrint.options.apikey携带管理员 API Key,还是依赖登录会话 + CSRF Token,上述方法都能正常工作。

客户端参数校验通过OctoPrintClient.InvalidArgumentError(createCustomException("InvalidArgumentError"),定义于 src/octoprint/static/js/app/client/base.js)抛出,例如users.add缺用户名/密码、groups.add缺 key/name、所有按 key/name 定位的方法缺标识符时都会触发。

完整示例:面向多服务器的用户管理

以下示例演示如何实例化独立客户端并组合使用 access 组件的方法(参考 docs/jsclientlib/index.rst 的多客户端模式):

var client = new OctoPrintClient({ baseurl: "http://octopi.local/", apikey: "ADMIN_API_KEY" }); client.access.users.list() .fail(function (xhr) { if (xhr.status === 403) { console.error("需要管理员权限或近期凭据校验"); } }) .done(function (response) { // 过滤出当前激活的用户 var activeUsers = response.users.filter(function (u) { return u.active; }); console.log(activeUsers); }); client.access.groups.add({ key: "engineers", name: "Engineers", permissions: ["PRINT"], subgroups: ["users"], default: false }).done(function () { console.log("组已创建"); });

权限、安全与错误处理速查

综合 docs/api/access.rst、src/octoprint/server/api/access.py 与 src/octoprint/static/js/app/client/access.js,整理各方法的权限与典型错误如下:

方法权限要求底层端点典型错误
permissions.list无特殊要求GET/api/access/permissions—
users.listADMINGET/api/access/users403
users.getADMIN 或本人GET/api/access/users/<name>403 / 404
users.addADMINPOST/api/access/users400 / 409
users.updateADMINPUT/api/access/users/<name>400 / 404
users.deleteADMINDELETE/api/access/users/<name>400(删除自己)/ 404
users.changePasswordADMIN 或本人(本人需current)PUT/api/access/users/<name>/password400 / 403 / 404
users.generateApiKeyADMIN 或本人 + 近期凭据POST/api/access/users/<name>/apikey403 / 404
users.resetApiKeyADMIN 或本人 + 近期凭据DELETE/api/access/users/<name>/apikey403 / 404
users.getSettingsADMIN 或本人GET/api/access/users/<name>/settings403 / 404
users.saveSettingsADMIN 或本人(管理员需近期凭据)PATCH/api/access/users/<name>/settings403 / 404
groups.listSETTINGSGET/api/access/groups403
groups.getSETTINGSGET/api/access/groups/<key>404
groups.addADMIN + 近期凭据POST/api/access/groups400 / 409
groups.updateADMIN + 近期凭据PUT/api/access/groups/<key>403 / 404 / 409
groups.deleteADMIN + 近期凭据DELETE/api/access/groups/<key>403 / 404

几个值得注意的安全细节:

  1. 近期凭据校验:用户组写操作以及管理员代他人执行改密、API Key、设置等操作时,服务端强制要求近期凭据校验(require_credentials_checked_recently/ensure_credentials_checked_recently,见 src/octoprint/server/api/access.py),从而避免会话被长期借用后直接执行敏感操作。
  2. API Key 脱敏:users.list与users.get在凭据未近期验证时,返回记录中的apikey一律置为null(见get_users/get_user),防止敏感信息泄露。
  3. 内置组保护:admin、users、guest、readonly等默认组受GroupCantBeChanged/GroupUnremovable保护,删除或修改会分别收到 403。
  4. 循环子组引用:groups.add/groups.update若形成循环子组关系,服务端返回 409,客户端应捕获该错误并向用户提示。
  5. 删除自身限制:users.delete不允许删除当前登录用户,服务端返回 400。

扩展阅读与相关资源

  • 组件文档索引:docs/jsclientlib/index.rst(含客户端库的引入方式、OctoPrint全局实例与多客户端用法)
  • 底层 REST API 完整文档:docs/api/access.rst(端点、数据模型、错误码)
  • 客户端实现源码:src/octoprint/static/js/app/client/access.js
  • 客户端基础组件(请求原语与参数校验):src/octoprint/static/js/app/client/base.js
  • 服务端 REST 实现:src/octoprint/server/api/access.py
  • 权限模型:src/octoprint/access/permissions.py
  • 用户模型:src/octoprint/access/users.py
  • 用户组模型:src/octoprint/access/groups.py
  • 第三方客户端授权工作流可参考内置的 Application Key 插件文档:docs/bundledplugins/appkeys.rst,它为外部客户端补充了额外的 JS Client Library 方法,与本文的 API Key 机制互补。
  • 物联网
  • 后端

【免费下载链接】OctoPrint

OctoPrint is the snappy web interface for your 3D printer!

项目地址:https://gitcode.com/gh_mirrors/oc/OctoPrint
点击查看免费下载
上一篇:猫抓插件完整指南:3步玩转浏览器资源嗅探,网页视频下载不再求人
下一篇:FastAPI `BackgroundTasks` API 参考:响应发出后调度后台任务的声明式用法

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

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

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

立即咨询