תוכן עניינים

权限与数据范围

本文说明系统权限分为功能权限与数据范围两层:写操作由接口权限码拦截,数据范围以查询条件加入语句,但仅对留有归属字段的表生效,附件与外链不受权限管控。

  • 功能权限靠接口权限码卡住,全书统计在用的码为151个
  • 数据范围四档中只有销售配“仅自己”,条件加在查询语句上
  • 范围筛选依赖归属字段,没留归属格的表原样返回不筛
  • 附件走公开静态路径并带缓存,知道链接即可下载
  • 系统没有只读档,字段级权限有表但没接线

17.1 老陈提的那个要求,拆开是两件事

厂里第一次谈权限,老陈说得极直白:"小徐只能看他自己的客户,别人的别让他看。李卉的工艺别人改不了。财务的数,车间不许翻。"

三句话,其实是两件不同的事。

一件是能不能做这个动作:谁能改工艺路线、谁能审报价、谁能导客户清单。这叫功能权限。

另一件是同样一个动作,能对哪些数据做:都能改客户,但你只能改你名下的。这叫数据范围。

很多系统只做第一件,然后把结果叫"权限管理"。这套系统两件都有,而且第二件的做法比多数人想的更实在——它不是在前端把按钮藏了,是在查询语句上加条件。但正因为实在,它的边界也更值得说清楚:哪些地方这道墙是真墙,哪些地方它其实踩空。

17.2 功能权限:一张树、一组码、一道接口

权限点是一棵树:一级模块、菜单、操作点,种子登记了三百多个可选点,十四套角色各自勾选(挂得最多的那套一百二十九项)。

真正管用的不是这棵树,是接口上那道判断。每个写操作的入口都挂着一个权限码,请求进来先问一句:这个人身上的角色,有没有这个码。全书统计在册的在用码是一百五十一个(口径见前言基线表:这是接口真正卡了的码,与种子里那三百多个"可选点"不是一回事)。

这里有一条容易被忽略的设计取向,管理端和后端用同一个码名。前端有个判断函数管按钮显不显示,菜单也按同一批码过滤。所以"页面上没有那个按钮"和"接口不让你调",通常是同一件事的两种表现——不是前端演一下。

17.3 数据范围:四档,落在查询语句上

角色的数据范围有四档可选:不限、本部门、仅自己、按模块自定义。当前十四套角色的实配是:三套不限(管理员、超级管理员、经理),十套本部门,只有销售是"仅自己"。

"仅自己"落到代码上是这样:查客户的语句上自动加一个条件,负责人是我 或者 创建人是我。为什么要两个?因为厂里有两种真实情况——管理员替新来的销售建了客户再指派过去,以及从客户池里认领。这两种情况下创建人和负责人不是同一个人,只认一个就会让人看不见自己该干的活。这个取舍写在代码注释里,是想过再写的。

"本部门"更绕一点:先看这张表自己有没有部门格;没有,就把同部门的人查出来,再按"创建人在这几个人里"筛。

范围加在查询语句上,意味着换接口也绕不开——不是靠前端传一个"只看我的"开关。这一条是全章最该肯定的地方。

17.4 但范围是"有格子才筛"

接下来要说的,是这一章最硬的一段。

系统怎么知道"这条记录属于谁"?它的做法是看这张表有没有那几个字段:负责人、创建人、申请人、部门——有就加条件,没有就……原样返回,不加任何限制。

不是报错,是不筛。

于是有一类表天然在范围之外。最典型的是订单:这张表上没有归属字段。销售隔离只能沿着报价那条链建起来——判断你有没有权限时,去看这张订单是从哪份报价来的、那份报价是谁建的。这条链只在首批订单上是完整的;不经报价直接开出来的批量订单,链子中端就断了。

推而广之:凡是没留归属格的那张表,"仅自己"这一档都管不到它。 老陈那句"别人的别让他看",在有归属格的档案上是真的,在没归属格的表上不会自动成立。这不是配置能解决的,是建表时就得决定"这条记录要不要知道它是谁的"。

17.5 三个做到位的细节

既然要说清边界,也得把做得对的地方写明,它们在实施时是省事的。

  • 单条也问一句。 客户这条线,详情、修改、删除、跟进四个入口都先做一次范围判定:按编号取一条,套上范围条件,取不到就回"无权操作该客户(超出您的数据范围)"。光把列表筛干净是不够的——很多人是通过改地址栏里的编号越权的,这一步补上了。
  • 不让审批人被范围挡在门外。 订单查询的可见范围是"你的数据范围"并上"当前轮到你在批的单子"。否则一个部门经理设了"仅自己",待办红点亮了、点进去却是空的。审批工作台用的是同一口径。
  • 越权时说"不存在"。 打印某份报价流程时,范围条件加在报价那张表上;不在你范围内,回的是"订单不存在或不在您的数据范围内"。不告诉你它存在——存在性本身也是信息。

17.6 两处口子,和一个反向默认

其一:免登录的口子。 有一小批接口挂在认证白名单里:登录、注册、退出、令牌刷新、钉钉扫码验证,还有一个扫码解析物料的接口(注释写的是移动端要用)。前几个本该公开;最后那个是往库里写请求的入口,传一串二维码内容进去,回的是这条物料的完整信息。没登录也能问出一件物料的家底。

其二:附件是敞开的大门。 上传目录既被后端当静态资源挂载,也在网关上以公开静态方式放出(还带三十天公共缓存)。这条路径不需要登录,也不需要令牌——知道链接就能取到文件。而这个目录里放的是什么?报价图纸、客户确认书、拒绝依据、开票与收款凭证。前面所有的权限判断,管的是接口,管不到一条已经发出去的文件链接。

其三:默认方向是反的。 取一个人的范围档时,代码兜到底会给"仅自己"(拿不到就算严),这是对的。但执行过滤那一头,如果档位的值不是那四个词中的任何一个,走的是最后的"不限制"。界面显示也更宽松:不认识的值一律显示成"仅自己"。同一种错法,屏上看着最严,跑起来最松。 现在库里十四套角色取值都规范,这条是潜在账,不是现行事故。

17.7 "可见即可操作"这句话的代价

这套系统的权限模型里没有"只读"这一档。一个权限点要么给,要么不给;给了菜单,就能进页面、能改、能存。想给一个人"能看不能改",唯一的办法是给他看列表接口、不给写接口——但列表页上的编辑按钮通常和列表用的是同一个菜单点,粒度对不齐。

再补一句第十五章已经查实的话:字段级的可见可改有表、没接线。所以"这个格子只有工艺员能改"这种要求,目前也落不了地。

老陈那句"财务的数车间不许翻"是能做的(不给码即可);"让车间看着财务的数但不许动",做不到。实施时提前把话说死,别拿"我们有字段权限"糊过去。

17.8 这一章不做的事

  • 不做行级授权规则引擎。 没有"满足某条件时某人可看某几条"这种可配规则;四档加字段推断是当前全部表达力。
  • 不做审批流内的数据可见性分级。 审批人看得到单据全部明细,不再按字段裁剪。
  • 不做文件级权限。 附件一旦有链接就等于公开,暂无签名地址与有效期机制。
  • 不宣称"所有接口都被权限码覆盖"。 写操作基本挂码,相当一部分查询接口只认登录态——登录之后能不能看,取决于它查的表有没有归属格。

17.9 今晚能定的三条

  1. 先只认一个事实:一个角色有没有那个码。 把十四套角色打印出来贴在办公室,逐条问"这个人在厂里真的该干这个吗"。权限表最可怕的不是配错,是没人复查过。
  2. 把附件链接当敏感信息管。 在实现文件鉴权之前,别把凭证与图纸的外链发到群里、写进邮件签名——这不是使用习惯问题,这条路径当前不设防。
  3. 给"要不要留归属格"定一条建表规矩。 从今往后任何新单据都问一句:这张表要不要知道它是谁的。要,就加负责人或创建人;不要,就明确它属于公共可见范围。这一条不定,17.4 那道口子只会越来越多。

这一章能定的事就一句:动作上的权限是真墙,数据上的范围取决于表有没有留归属格,文件根本没上墙。 三件事分开管,才对得起老陈那一句"别人的别让他看"。