
一、为什么一人多号是企业身份治理的老大难做企业身份管理IAM时最容易被人忽略、也最容易造成安全事故的不是某个系统没上多因素认证MFA而是同一自然人对应多个异构账号这个结构性问题。一个在集团工作五年的员工他的身份痕迹通常散落在这些地方HR 系统里有一份用工记录主键是工号微软 Active Directory 里有一个域账号用于办公电脑登录与邮箱一套 OpenLDAP 目录里为了老应用兼容又存了一份账号命名规则是拼音缩写OA 系统、ERP、CRM、邮件系统各自再建一套本地账号密码策略五花八门堡垒机、服务器、网络设备用 RADIUS 纳管账号名往往又是另一套云桌面、共享业务账号里还可能有人共用一个部门公共号。结果就是张三这个人在企业的身份台账里实际存在 6 到 10 个身份实体但没有任何一处把它们明确指认为同一个自然人。这正是主数据治理MDM在身份领域要解决的核心命题——建立唯一的身份标识也就是常说的 One Identity。1.1 多号并存带来的三类直接伤害伤害类型具体表现合规与业务后果审计断链张三的 OA 操作、堡垒机登录、ERP 审批分别记在不同系统无法归属到同一人等保2.0三级要求应对用户行为和重要安全事件进行审计出事难以责任溯源权限冗余离职人员 AD 账号已禁用但 LDAP、OA、某业务库还留着活跃账号影子账号成为横向移动跳板攻击面收敛不彻底共享账号泛滥一个部门公共号多人使用谁操作无从区分账号共享治理缺位严重违反最小授权与审计可举证原则可以直白地说没有唯一身份标识所谓统一身份认证只是把多个入口换成多个入口 一个门户底层的身份账本仍然是割裂的。真正的单点登录SSO前提是先有一个可信的人的主体否则 SSO 只是把多个账号的登录体验叠在一起并没有解决身份归一。二、用户主索引 EMPI唯一身份标识的数据底座医院信息化领域早就遇到过类似问题——同一个病人在不同科室、不同医院有不同就诊卡于是引入了 EMPIEnterprise Master Patient Index企业主患者索引。在身份治理里我们借鉴同样的思想建立 EMPiEnterprise Master Person Index企业主人员索引以下简称 EMPI。EMPI 的核心思想只有一句话每个自然人只有一个全局主体Global Person ID, GPID所有异构账号都只是这个主体的本地视图。2.1 EMPI 的核心字段设计一个可落地的 EMPI 主体表建议至少包含如下字段empi_person { gpid string // 全局唯一自然人标识系统生成对外不可见语义 legal_name string // 法定姓名与证件一致 id_number_hash string // 证件号强烈建议存 SM3 哈希而非明文 employee_no string // 工号来自 HR 主数据 hr_status enum // 在职 / 离职 / 待入职 / 退休 org_path string // 组织路径用于授权与审批归属 primary_email string // 主邮箱常用匹配键 created_at datetime // EMPI 记录创建时间 source_systems json // 该自然人关联的所有源系统与本地账号引用 confidence float // 归并置信度0~1 merge_state enum // SINGLE / MERGED / CONFLICT / MANUAL updated_at datetime }注意id_number_hash与employee_no证件号是最强的自然键但在身份系统里存明文证件号本身又是合规风险。正确做法是只存经过国密 SM3 摘要后的值匹配时同样对输入做 SM3 后再比对既保证能精确归并又不泄露原始敏感信息。这一点恰好契合等保2.0对个人敏感信息应加密存储的要求。2.3 匹配键的选取与质量评估EMPI 能不能建得准七分靠源数据质量三分靠匹配算法。在动手写匹配代码之前建议先对各大源系统做一次匹配键健康度评估核心看三件事第一唯一性某字段在源系统内是否全局唯一。工号理论上唯一但很多企业的 HR 系统存在借调工号“外包工号”历史工号复用等情况需要先用 SQL 跑一遍去重确认没有两个自然人共享同一工号。一旦存在共享工号它就从强键降级为弱键必须叠加其他字段才能归并。第二稳定性字段会不会随业务频繁变化。姓名会变结婚、生僻字正音手机号会变部门会变相比之下工号和证件号是稳定键。匹配策略应当优先信任稳定键对易变字段只作辅助证据避免因为一次部门调动就错误拆散或错误合并同一人。第三覆盖率字段在源系统里是否为空。老系统最容易缺证件号OA 系统最容易缺工号。覆盖率低的字段不能单独作为强键必须设计回退链路——工号缺失时退回证件哈希证件哈希也缺失时退回主邮箱层层兜底才能让归并规则在全量数据上跑得通而不是只在干净样本上成立。这套评估最好在匹配引擎上线前以离线报告的形式交付给 HR 与 IT 管理员确认因为它直接决定后续归并的置信阈值定在哪里。数据质量评估本身不是技术炫技而是把系统里到底有多少可信的主数据这件事先摊开说清楚避免后续把算法背锅成归并不准。2.2 异构账号如何挂到 EMPI 上每个源系统的本地账号单独存一张映射表account_link { link_id string gpid string // 指向 empi_person.gpid source_system string // HR / AD / LDAP / OA / ERP / RADIUS / 堡垒机 local_account string // 该系统内的账号名 local_id string // 该系统内的主键 match_key string // 本次建立关联所用的匹配键工号/证件哈希/邮箱 match_method enum // AUTO / RULE / MANUAL bound_at datetime status enum // ACTIVE / DISABLED / ORPHAN }这张表的意义在于任何一次登录、操作、审批只要能拿到source_system local_account就能 O(1) 反查出背后的gpid。跨系统审计链路连续性的根基就在这里——无论行为发生在 OA 还是堡垒机最终都归因到同一个自然人。三、账号归并策略从匹配规则到冲突消解EMPI 只是容器真正把散落的账号认出来是同一人的是账号归并策略。归并策略一般分三层确定性匹配、概率性匹配、人工确认兜底。3.1 确定性匹配规则强键匹配强键是指几乎不可能冲突、且源系统普遍维护的字段。优先级从高到低工号employee_noHR 是权威源凡带工号的账号直接归并证件号哈希id_number_hash无工号的老系统用 SM3 证件哈希匹配主邮箱primary_email邮箱后缀可控的内网场景邮箱前缀往往与工号强相关。确定性匹配的实现伪代码def deterministic_match(account): # 依次尝试强键命中即归并 if account.employee_no: p empi_find_by_employee_no(account.employee_no) if p: return merge(p, account, keyemployee_no) if account.id_number: h sm3(account.id_number) # 国密摘要后再比 p empi_find_by_id_hash(h) if p: return merge(p, account, keyid_hash) if account.email and is_internal_domain(account.email): p empi_find_by_email(local_part(account.email)) if p: return merge(p, account, keyemail) return None # 未命中进入概率匹配3.2 概率性匹配弱键模糊匹配很多历史系统的账号只有姓名 部门 手机号后四位这类弱键单独任一字段都不够确定但组合起来可以给出置信度。常用做法是加权打分def probabilistic_match(account): candidates empi_candidate_by_name(account.name) # 同名候选集 best, best_score None, 0.0 for c in candidates: score 0.0 if c.dept account.dept: score 0.30 if c.phone_tail account.phone_tail: score 0.25 if c.org_path.startswith(account.org_prefix): score 0.20 if same_birth_month(c, account): score 0.15 if c.hire_date account.entry: score 0.10 if score best_score: best, best_score c, score if best_score 0.85: return merge(best, account, keyprob, confidencebest_score) if best_score 0.55: return flag_for_review(best, account, best_score) # 进入人工确认 return create_new_person(account) # 低置信视为新人这里的阈值需要结合企业实际数据分布调参阈值设太高会漏归并还是多号设太低会误归并把两个重名的人并成一个。稳妥做法是先离线跑全量匹配、抽样人工校验、再选定阈值而不是凭拍脑袋。3.3 冲突消解Conflict Resolution归并最怕两强相遇A 账号已经归到 GPID-001B 账号又强键命中 GPID-002但系统发现 GPID-001 和 GPID-002 其实是同一人比如早期两个 HR 工号并存。这时不是简单覆盖而是要做主体合并并保留合并轨迹def resolve_conflict(gpid_a, gpid_b, evidence): # 证据充分如两主体证件哈希相同才合并 if same_id_hash(gpid_a, gpid_b) or same_employee_no(gpid_a, gpid_b): survivor older_or_more_complete(gpid_a, gpid_b) loser the_other(survivor) # 把 loser 的所有 account_link 改挂到 survivor reparent_links(loser, survivor) # 记录合并事件保留可审计的溯源链 log_merge(survivor, loser, evidence, operatorsystem) mark_merge_state(survivor, MERGED) return survivor else: flag_for_review(gpid_a, gpid_b, reasonconflict_needs_human)关键原则是合并必须留痕。每一次 reparent、每一次 merge 都要写进审计账本说明为什么把 B 并到 A否则后续责任溯源会出现这个人怎么有两个 GPID的扯皮。等保2.0三级强调审计记录要能追溯到操作归并操作的留痕本身就是合规的一部分。3.4 人工确认兜底无论确定性还是概率性匹配都绕不开一个事实数据质量是有限的。对于置信度落在灰色区间或命中冲突的案例必须有人工确认环节。落地时建议建一个待确认归并工单池由 HR 或身份管理员逐条确认每条待确认记录展示两端账号的可用证据工号、部门、证件哈希前缀、入职日期降低确认成本确认动作本身也要签名留痕操作者、时间、结论满足审计可举证。以安当ASP为例它的身份目录把 SSO、MFA、OTP、RADIUS、SLA、SYP 六大模块架在同一套主体之上EMPI 这类唯一身份标识一旦建立SSO 在签发会话时拿到的不是某个应用账号而是背后的 GPIDRADIUS 纳管的网络设备和堡垒机登录也能通过 account_link 反查到同一自然人。理解到这一层就能明白账号归并不是要在认证平台之外再造一个系统而是把人这个主体先理顺再让各认证协议去引用它。四、审计链路如何连续跨系统行为归属同一自然人归并完成后真正的价值要在审计环节兑现。传统审计最大的痛点是日志各记各的OA 记一条操作堡垒机记一条登录ERP 记一条审批三张表之间没有外键出了安全事件要靠人工去拼这到底是不是同一个人干的。4.1 统一审计事件模型归并之后所有系统的审计事件统一带一个gpid字段audit_event { event_id string gpid string // 一律归因到自然人 source_system string // 事件来源 local_account string // 当时的本地账号保留便于核对 action string // login / approve / query / download ... result enum // SUCCESS / FAIL / DENY ts datetime // 时间戳 src_ip string risk_score int // 本次风险评分 signature string // 事件 SM3 签名防篡改 }这样,无论行为发生在哪套系统只要gpid相同就能把一个人的全部行为按时间线串起来。安全团队做一次某人近 30 天全行为画像不再需要跨 11 个系统写 11 条 SQL。4.2 连续性的两个工程要点第一归并要向前兼容历史日志。很多项目只对新事件打gpid历史日志还是老账号。正确做法是做一次回填用最终确认的 account_link 把历史审计日志里的local_account source_system也映射上gpid否则责任溯源会出现归并前的行为找不到人的断层。第二账号禁用 / 离职要级联。员工离职时HR 主数据把hr_status置为离职EMPI 应触发级联所有account_link关联的 AD、LDAP、OA、RADIUS 账号统一禁用且这条级联动作本身写进审计账本。避免出现AD 禁了、OA 还活着的权限冗余。这正是账号共享治理与身份生命周期管理的交汇点——身份不是静态快照而是随 HR 状态流动的事件流。五、与统一认证平台对接异构账号映射到统一主体EMPI 解决人是谁统一身份认证平台解决人怎么登录、怎么被授权。两者对接的关键是把 SSO 的认证结果从本地账号升级为GPID 主体。5.1 SSO 登录时的主体解析以 SAML2.0 / OIDC 为例认证平台在收到断言assertion后不直接信任断言里的 NameID而是做一次 GPID 解析func resolve_principal(saml_assertion): local_account saml_assertion.name_id source_system saml_assertion.issuer // 哪个 IdP 发的 link account_link_find(source_system, local_account) if link is None: # 找不到映射可能是孤儿账号或新账号 return HANDLE_ORPHAN(local_account, source_system) person empi_get(link.gpid) if person is None: return DENY(person missing) if person.hr_status LEAVE: return DENY(employee left) # 签发会话时携带 GPID而非本地账号 session issue_session(gpidperson.gpid, displayperson.legal_name, rolesderive_roles(person)) audit.log(gpidperson.gpid, actionsso_login, resultSUCCESS) return session这一步把用哪个账号登录和这个人是谁彻底解耦业务系统拿到的会话主体永远是 GPID底层到底是 AD 账号还是 LDAP 账号业务系统无需关心。后续即便某个源系统账号改名、合并业务侧无感。5.2 孤儿账号清理对接过程中必然会暴露出一类账号在源系统里存在但在 EMPI 里找不到任何自然人归属也没有account_link。这就是孤儿账号orphan account。它们往往来自历史遗留、离职未清理、或测试账号。清理分三步识别全量扫描各源系统账号与 account_link 做差集得到孤儿清单定性区分待认领可能是新员工尚未建 EMPI、“疑似废弃”长期无登录、“确认废弃”离职人员残留处置待认领的进入人工确认池确认废弃的直接禁用并归档处置动作全程留痕。孤儿账号清理是账号共享治理里最容易被忽略、却最见成效的一环。一个常见的落地指标就是孤儿账号占比——归并前可能高达 15%~30%治理后应压到个位数。5.3 与多因素认证MFA的协同唯一身份标识建立后MFA 策略也能更精准。过去 MFA 是按账号开现在可以按主体开GPID 一旦被标记为高风险如近期有异地登录、设备异常所有挂在它名下的系统登录都强制二次认证而不是只拦其中一个应用。身份归一让风险策略第一次有了以人为单位的抓手。六、落地指标体系怎么证明归并做对了任何治理项目都要回答凭什么说有效。账号归并建议盯四类指标指标定义治理前典型值治理目标账号重复率账号总数 - GPID 数/ 账号总数40%~60% 10%登录入口收敛度支持 SSO 的系统数 / 总系统数30% 90%审计覆盖率带 GPID 的审计事件 / 总审计事件偏低100%孤儿账号占比孤儿账号 / 账号总数15%~30% 5%需要提醒的是这些指标不是达标即结束。账号归并是一项持续运营每天都有新员工入职、老员工调岗、离职人员清理EMPI 要有增量匹配与定时体检机制。很多项目上线时指标漂亮半年后重复率又反弹根因就是只做了一次性归并、没有持续运营。以安当ASP为例它支持的 LDAP / RADIUS 协议正好对应企业里最难归一的两类账号源——目录类与服务接入类。把这两类账号也纳入 account_link 映射后统一身份认证平台在 SSO 时就能把网络设备登录、服务器登录、OA 审批全部归因到 GPID等保2.0三级要求的审计记录应包括事件的日期和时间、用户、事件类型才真正能串成一条完整的自然人责任链而不是散落在网管日志、应用日志里的碎片。七、一个市级民政局的真实缩影某市级民政局此前有 11 套业务系统各自一套账号体系员工办事要记 11 套密码登录平均耗时约 3 分钟。更关键的是审计各自为政无法对一个经办人跨系统的操作做整体责任认定。在引入 EMPI 与统一认证平台后他们做了几件事先以工号为强键、证件号 SM3 哈希为次键把 11 套系统的账号全部建立 account_link再对少量历史遗留的重名账号走人工确认兜底最后让 SSO 统一签发 GPID 会话并做全量历史日志回填。结果是登录入口收敛到单点平均登录时间从 3 分钟降到 10 秒左右跨系统行为第一次能归因到同一自然人审计覆盖率达到完整孤儿账号从几十个清理到个位数。这个项目里没有增加任何新业务功能纯粹是把人这一层主数据理顺收益却直接体现在效率与合规两条线上。八、常见踩坑与规避只建 EMPI 不动账号以为有了唯一标识就万事大吉结果各系统本地账号还是各用各的GPID 成了另一张表没有下沉到 SSO 解析环节。EMPI 必须接入认证链路才产生价值。明文存证件号为图匹配方便把身份证号明文入库反而制造合规雷点。务必 SM3 摘要后存储与比对。阈值拍脑袋概率匹配阈值不抽样校验就上线导致大量误归并或漏归并。上线前必须离线跑全量 人工抽样。不回填历史日志只对新事件打 GPID历史审计断层责任溯源断裂。历史日志回填是连续性的前提。归并不留痕主体合并、账号 reparent 不写审计事后查不清为什么这两个人是一个。合并动作必须签名留痕。一次性运动式治理上线即终点半年后重复率反弹。EMPI 需要增量匹配与定时体检的持续运营机制。方案参考账号归并与唯一身份标识One Identity的本质是主数据治理在身份领域的具体落地并不依赖某个特定产品。任何组织在推进企业身份管理现代化时可参考以下通用方法论先立唯一主体再做统一认证在接入单点登录SSO之前先建立以 GPID 为核心的 EMPI把人这个主体从散落的本地账号中抽象出来避免 SSO 只是把多个入口叠在一起。强键优先弱键兜底人工收口匹配规则先用工号、证件号哈希、主邮箱这类强键做确定性归并再用加权概率匹配处理弱键场景最后对灰色区间与冲突案例一律人工确认任何归并都要留痕可溯源。敏感键国密摘要存储证件号等个人敏感信息只存 SM3 哈希匹配时同算法摘要后比对兼顾精确归并与等保2.0对敏感信息加密存储的要求。审计事件统一带 GPID所有系统的认证、操作、审批事件归因到同一自然人并对历史日志做回填确保跨系统责任溯源连续不断层。身份随 HR 状态流动离职、调岗等状态变化应级联禁用或重新映射各源系统账号杜绝权限冗余与影子账号这是账号共享治理的底线。持续运营而非一次性项目建立增量匹配与定时体检机制持续监控账号重复率、登录入口收敛度、审计覆盖率、孤儿账号占比四项指标防止治理成果反弹。以上方法论与具体实现无关是身份主数据治理的通用骨架。真正的难点从来不是协议选型或工具引入而是把散落在 HR、AD、LDAP、OA、RADIUS 与各业务系统里的同名异构账号重新认领回同一个自然人并让这条唯一身份标识持续、准确地运转下去。