> 选题编号:20(权限与域验证)
在仓库管理系统里,"能不能看"和"能不能改"从来不是一个可有可无的附属功能。一套 WMS 上线之后,仓管员、拣货员、叉车司机、客户货主、财务对账人员、总部运营,几十号甚至上百号人会在同一套系统里同时操作。如果权限只做到"菜单能不能点"这一层,就会出现很典型的现场事故:A 货主的库存被 B 货主的客服看到了,某仓的盘点差异表被另一个仓的人导出走了,临时工账号离职三个月还在能改出库单。
这类问题在单仓单货主的场景里不明显,一旦走到多仓、多货主、3PL 第三方物流,就会变成不可接受的事故。本文结合 JeeWMS 的实现,聊聊 Java 开源 WMS 的权限体系与"域验证"该怎么做,以及二次开发时如何在扩展模块里沿用同一套机制。
认准官方仓库 gitee.com/erzhongxmu/JEEWMS,注意辨别第三方镜像或 fork。仓库地址:https://gitee.com/erzhongxmu/JEEWMS
一、为什么 WMS 的权限比普通后台系统更复杂
普通的 OA 或 CRM,权限模型通常是"用户---角色---菜单/按钮"。WMS 在此之上还多了一个维度:**数据域(Domain)**。
同一个人,在不同数据域里看到的东西完全不同:
-
一个区域仓管,只能看到自己负责的几个仓库,跨仓的库存汇总不该出现在他的列表里;
-
一个货主账号登录进来,只能看到属于自己的货品、订单、账单,即使这些数据物理上和其他货主放在同一张表里;
-
一个承运商账号,只应看到与自己相关的运输任务和月台预约,看不到仓租费率;
-
总部运营可以横向看全部数据,但操作按钮(审核、冲销、调账)依然受职能角色约束。
也就是说,WMS 的权限至少要拆成两层:**功能权限**(能做什么操作)和**数据权限**(能看到哪些数据)。前者是角色定义,后者是"域验证"------在每一次查询、每一次保存前,确认当前用户所处的域,并把域条件自动注入到数据访问环节。
JeeWMS 在模块设计上把"域验证"单独列为一个功能单元,和权限管理并列,正是因为它不是权限的子功能,而是一套贯穿全局的约束机制。
二、JeeWMS 的权限与域验证机制拆解
1. 组织、角色与用户:三层授权
系统的授权结构沿用了比较经典的组织---角色---用户模型:
-
**组织**:对应公司、仓库、部门等实体层级,是数据域的天然边界;
-
**角色**:承载功能权限,一个角色绑定一组菜单、按钮、接口权限;
-
**用户**:归属组织,可分配多个角色,最终权限是角色权限的并集。
在这个模型下,"某仓管员只能管 A 仓"不是靠给每个菜单单独配规则实现的,而是靠用户所属组织 + 组织与仓库的归属关系推导出来的。这样做的好处是新增仓库时,只要把仓库挂到对应组织下,权限自动跟随,不需要重新配一遍。
2. 域验证:把数据边界做成可插拔的约束
所谓域验证,就是在数据访问入口处统一做一次"当前用户能碰哪些数据"的判定。落到工程实现上,通常包含三件事:
**(1)域的识别。** 登录成功后,把用户的组织链路、可访问仓库集合、所属货主(如果是货主账号)等信息解析出来,放进会话上下文。这一步只做一次,后续请求直接复用,避免每次查询都去递归查组织树。
**(2)域条件的注入。** 在持久层做统一拦截,为查询自动追加域过滤条件。JeeWMS 的持久层基于 Hibernate 与 Minidao,SQL 与实体操作都在这层收口,因此可以在这一层统一追加仓库、货主、组织等维度条件,而不需要在每个业务方法里手写 `and warehouse_id in (...)`。
**(3)写入侧的校验。** 查询过滤只是"看不见",写入侧还必须做"改不了"。保存、审核、删除、导出这些动作,都要先取出目标记录,判断其所属域是否在用户域集合内,不在则直接拒绝。只做查询过滤不做写入校验,是最常见的越权漏洞来源。
3. 与多货主、多仓场景的配合
在 3PL 场景下,同一套系统里跑着几十个货主的货。域验证的价值在这里被放大:
-
**库存查询**:货主账号只能查自己货品的库存,仓管账号可以按仓查全部货主;
-
**计费账单**:动态计费引擎算出来的仓储费、操作费,账单只能流转到对应货主与对应财务角色;
-
**月台与预约**:承运商只能看到与自己相关的预约单,避免运力计划外泄;
-
**盘点与调账**:盘点差异的审批流绑定职能角色,调账动作留痕,且不能跨货主执行。
这些规则如果用 if-else 写在业务代码里,很快就会失控。把它们收敛到域验证层,业务代码只关心业务逻辑,是更可持续的做法。
三、二次开发时如何沿用这套机制
很多团队拿到开源 WMS 后会做二次开发,最常见的坑就是"新写的接口忘了做域校验"。以下是在 JeeWMS 上扩展模块时的几条实践建议:
**第一,新表要带域字段。** 凡是业务数据表,建议预留仓库、货主、组织这类域字段。没有域字段的表,后续想加数据隔离基本等于重写。
**第二,新接口走统一的持久层入口。** 不要图省事绕过框架自己拼 SQL 直连数据库,那样会绕过域条件注入,等于开了后门。
**第三,导出与报表单独加固。** 列表查询被域过滤了,不代表导出接口也过滤了。导出往往是批量拉取,一旦越权,泄露量比单条查询大得多。
**第四,接口对接同样要带域。** 与 SAP ECC、SAP HANA、用友 U8、百胜 E3 等外部系统对接时,接口调用方的身份也要映射成一个内部用户/域,不能因为是系统间调用就默认全量数据可见。
**第五,权限变更留痕。** 谁在什么时候给谁加了什么角色,这类操作本身要有审计日志,方便事后追溯。
最新版本基于 Spring Cloud 微服务架构 + Vue 前端,权限与域验证天然适合放在网关与统一鉴权层做第一道拦截,业务服务再做一次细粒度校验,双保险。
四、从权限体系看一套 WMS 是否"能上生产"
评估一套开源 WMS 能不能真正用于生产,权限与数据隔离是很硬的一条线。可以顺着这几个问题自查:
-
功能权限和数据权限是不是分开设计的?只有前者的话,多货主场景基本没法用;
-
域条件是统一注入还是各写各的?后者意味着每次改需求都有漏网之鱼;
-
写入、审核、导出是不是都做了域校验?只做查询过滤的不算完整;
-
新增一个仓库或货主,需要重新配多少东西?配置量越大,越容易出错;
-
PDA 端与 WEB 端是否共用同一套权限?移动端常常是权限薄弱点。
JeeWMS 的 PDA 端基于 UNI-APP 实现,与 WEB 端共用后端鉴权,现场作业账号同样受域约束,这一点在移动作业场景里很重要------扫码枪拿到手的人,不该因为设备形态不同就获得更大的数据面。
五、未来方向:把域验证交给智能体
权限与域验证本质上是"规则",而规则正是智能体擅长承接的部分。JEEWMS 背后是正在构建的工业互联网智能体平台------用 AI Agent 贯穿 WMS 仓储、MES 制造执行、ERP 企业资源、CRM 客户关系等业务域,把仓储沉淀的领域经验与大模型能力结合,走向智能调度、智能排产与 AI 运维,让工业场景从信息化迈向智能化。届时,异常越权访问的识别、权限配置的智能体检、跨系统域映射的建议,都有可能由智能体自动完成,人只需要做最终确认。
六、小结
权限不是 WMS 的边角料,而是它能不能被信任的地基。功能权限决定"能做什么",数据域决定"能看到什么",两者都做到位,多仓多货主、3PL 计费、移动作业这些复杂场景才立得住。
如果你正在选型或自己搭一套仓库管理系统,建议把权限与域验证作为第一条评估项,优先看它的域条件是统一注入还是各处手写。
JeeWMS 是 GPL-3.0 协议的开源 Java 仓库管理系统,覆盖进货、出货、退货、库内管理、盘点、库存查询、PDA 作业、分析报表与计费等模块,代码完全开放,可以直接下载阅读权限与域验证相关实现。
项目地址:https://gitee.com/erzhongxmu/JEEWMS
使用过程中遇到问题或有功能建议,可在 Gitee 仓库的 Issue 区交流反馈。