6.5 KiB
认证与第三方登录(crm-auth)
围绕三方扫码登录、本地用户定位与身份绑定的领域语言。
Language
孤儿身份: 三方身份绑定(identity)仍存在,但其指向的本地用户已被物理删除的状态。持有孤儿身份的人再次登录时,按手机号匹配或首登注册重新定位用户,并把原绑定重定向到新用户,避免下次登录再次命中孤儿。 Avoid: 脏数据、失效绑定
主部门: 一个用户唯一的正式归属部门,代表其组织身份与汇报线,用户信息展示、组织架构归位均以主部门为准。每个用户至多一个主部门。 Avoid: 归属部门、默认部门
兼职部门: 用户除主部门之外额外挂靠的部门,代表其参与该部门业务但组织身份不在其中。一个用户可有多个兼职部门,也可以没有。 Avoid: 副部门、附属部门
只读挂靠: 兼职部门当前的权限语义:用户能读到兼职部门范围内的数据,但其自身产出的业务数据恒归属主部门,不进兼职部门。因此兼职部门的管理者看不到该成员在本部门产出的数据。 Avoid: 双向兼职、完全平等
部门集合: 一个用户的主部门与全部兼职部门的并集,数据范围计算以该集合为输入,集合内各部门地位平等。 Avoid: 权限部门、可见部门
一律不可见: 数据范围档位要求按部门过滤,但该用户的部门集合为空时的判定结果:按部门归属的数据一行都不可见。无归属不等于全放行,此时查询注入永假条件而非放弃过滤。它是权限判定的结论,不是查询恰好没有命中数据。 Avoid: 空结果、查无数据、不过滤
在职状态: 用户的雇佣状态:在职 / 离职。来源于 OA 系统,CRM 不产生、只消费;离职用户仍保留在用户列表中(名下可能仍挂有业务数据),而非删除。与“账号是否可登录”是两回事——离职账号应禁止登录,被禁用的在职账号仍是在职。 Avoid: 员工状态、在职/离职员、启用状态
用户: 本系统中来自 OA 的人员统一称“用户”,不使用“员工/用工”。用户基本信息(姓名/部门/职务/手机号/在职状态)唯一来源为 OA,CRM 不产生、只消费。 Avoid: 员工、用工、人员
待分配用户: 在职且未持有任何角色的用户。该指标提醒管理员“有新人尚未配权限”;离职用户不计入,无论其是否持有角色。 Avoid: 无角色用户、未授权用户
免登: 用户在浏览器侧已登录钉钉后访问 CRM 时,前端重定向到钉钉 OAuth 授权页,钉钉检测到已登录态后自动重定向回 CRM 并携带 authCode,前端将 authCode POST 到现有扫码登录端点完成登录。免登与扫码登录在后端走同一套 OAuth2 userAccessToken 换取逻辑,区别仅在前端获取 authCode 的方式(重定向 vs 扫码),后端无感知。 Avoid: 自动登录、SSO、静默登录
组织准入: 登录流程中对新用户的组织归属校验:当用户在本地 DB 中查不到时,用企业级 access token 调钉钉组织通讯录 API(按 unionId 查询),确认该用户属于本企业后才允许自动注册。不属于组织的用户拒绝登录并返回「不属于该组织」错误。已在 DB 中的用户不受此校验影响(登录时不重复校验)。 Avoid: 组织校验、企业校验、准入检查
企业级 token: 用 clientId + clientSecret 向钉钉换取的组织级 access token,用于调用组织通讯录等需要企业身份的 API。与登录流程中的用户级 token(userAccessToken)不同:企业级 token 代表应用/组织身份,用户级 token 代表个人身份。缓存于 Redis,TTL 略低于钉钉颁发的 7200 秒有效期。 Avoid: corpToken、应用 token、组织 token
权限资源树: RBAC 的统一可授权资源模型:菜单分组(catalog)、菜单页面(menu)、按钮/权限点(button)三类节点在同一张 sys_menu 表中扁平存储,通过 parentId 组成树。catalog 是收纳容器不承载页面,menu 是可导航的页面,button 是挂在其下的叶子权限点。三层固定层级:根→catalog/menu→menu→button,分组不嵌套、按钮必挂页面下。 Avoid: 菜单表、资源表、权限树
权限码并集: 用户登录后,其所有角色授权的按钮节点(type=button 且 status=enabled)的 perms 字符串收集而成的集合,与 roleCode 一起注入 Spring Security authority,使 @PreAuthorize(hasAuthority('crm:xxx:yyy')) 生效。停用的权限点不进并集(全局断路),无需逐角色取消授权。 Avoid: 权限集合、按钮权限列表
权限点停用: button 节点的 status=disabled 状态:即使已被角色授予,权限解析引擎也不将其 perms 纳入权限码并集——相当于全局断路。重新启用后原授权自动恢复,无需管理员重新勾选。停用/启用只改 status 字段,不涉及角色授权关系变动。 Avoid: 权限删除、授权撤销
角色授权集合: 一个角色被授予的全部资源节点 ID,存储于 sys_role_menu 表。保存时由后端沿 parentId 向上遍历补全祖先 catalog/menu 节点(ADR-0005),因此存储态始终是一棵完整子树——用户勾选了某 button,其所属的 menu 和 catalog 一定也在集合中。角色详情接口返回此完整集合,前端直接用于渲染勾选状态,无需二次补全。API 层称 resourceIds,存储层为 sys_role_menu.menu_id。 Avoid: 菜单ID列表、menuIds(API 层术语)、勾选项
祖先补全: 角色权限保存时的后端操作:对前端传入的每个勾选节点 ID,沿 parentId 递归向上收集祖先 catalog/menu ID,合并入集合后再入库。保证菜单可见性链路完整——若只存叶子 button 而不补全其祖先 menu/catalog,权限解析引擎建菜单树时祖先不在授权集合中,用户虽有按钮权限却看不到所在页面。补全发生在存储时而非读取时,读取返回的就是已补全的完整集合。 Avoid: 前端补全、读取时补全
内置角色: SysRole 表中 builtin=true 的角色,代表系统运行所必需、不可删除、不可改 roleCode 的角色。ADMIN 是典型内置角色——若被删除,持有它的用户瞬间失去全部管理权限,系统不可恢复。builtin 字段由数据初始化器设置,创建角色接口不允许设 builtin=true。其他字段(roleName、dataScope、sort、remark)可正常编辑。 Avoid: 系统角色、固定角色、超级管理员