From 61a3000bee2783e4b2d213e43ebe237bee37d93e Mon Sep 17 00:00:00 2001 From: lijing Date: Mon, 12 Oct 2026 16:41:09 +0800 Subject: [PATCH] =?UTF-8?q?fix(auth):=20=E5=BD=93=E5=89=8D=E8=BA=AB?= =?UTF-8?q?=E4=BB=BD=E4=BC=98=E5=85=88=E6=8C=89=20roleName=20=E5=88=A4?= =?UTF-8?q?=E5=AE=9A=EF=BC=8C=E5=85=8D=E7=96=AB=E8=A7=92=E8=89=B2=E5=8F=B7?= =?UTF-8?q?=E9=85=8D=E7=BD=AE=E6=BC=82=E7=A7=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - matchCurrent 改为「先 roleName、再 roleId」:平台下发的 roleName(老师/校领导/学生/ 家长/局领导/工作号/管理员)是平台权威标签,先认名称可避免部署环境里 agent.roles.* 被旧角色号覆盖时把身份判错(现象:老师账号显示成「学生」) - ADMIN_WORDS 去掉「主任」(与「班主任」冲突会误判为管理员),补「教导」「职工」等 - 构造时 INFO 打印本次生效的角色配置,配置漂移一眼可见 - 测试 48/48 通过 --- .../com/yunhai/agent/auth/RoleResolver.java | 47 ++++++++++++++----- 1 file changed, 36 insertions(+), 11 deletions(-) diff --git a/src/main/java/com/yunhai/agent/auth/RoleResolver.java b/src/main/java/com/yunhai/agent/auth/RoleResolver.java index 6301057..19bb4b1 100644 --- a/src/main/java/com/yunhai/agent/auth/RoleResolver.java +++ b/src/main/java/com/yunhai/agent/auth/RoleResolver.java @@ -36,24 +36,32 @@ import java.util.concurrent.ConcurrentHashMap; * *

判定顺序

*
    - *
  1. 当前身份:先按 {@code roleId} 命中 {@code agent.roles.*}; - * 角色号没配到,再按 {@code roleName} 关键词兜底(老师/教师/班主任 → 教师, - * 管理员/校长/主任/教务… → 管理员,家长 → 家长,学生 → 学生);命中即只返回该身份;
  2. + *
  3. 当前身份:先按 {@code roleName} 关键词判定(老师/教师/班主任 → 教师, + * 管理员/校长/局领导/教务… → 管理员,家长 → 家长,学生 → 学生); + * 名称看不出身份的(如「工作号」)再按 {@code roleId} 命中 {@code agent.roles.*}; + * 命中即只返回该身份;
  4. *
  5. 当前身份是管理员时,按 {@code admin-also-teacher=true} 追加教师能力;
  6. *
  7. 无当前身份(或当前身份识别不出)→ 回退按 {@code roleIds} 逐个匹配配置;
  8. *
  9. 仍然什么都没识别出 → 按 {@code BoaUser.type} 兜底(0=学生、2=教职工、1=超管);
  10. *
  11. 什么都识别不出 → 访客(仅公共只读能力)。
  12. *
+ * + *

★ 为什么 {@code roleName} 优先:它是平台下发、与门户顶栏一致的权威标签, + * 先认名称可避免部署环境里 {@code agent.roles.*} 配置漂移(被旧角色号覆盖)把身份判错。 */ @Slf4j @Component public class RoleResolver { - /** 角色名关键词:命中即判定(角色号未配置时的兜底,跨学校更稳) */ + /** 角色名关键词:命中即判定(角色号未配置时的兜底,跨学校更稳) + * + *

★ 不含「主任」:它与「班主任」冲突,会把普通教师误判成管理员。 + * 教务主任/教导主任等仍可经「教务」「教导」… 命中,或由角色号配置兜底。 + */ private static final String[] ADMIN_WORDS = { - "管理", "校长", "园长", "局长", "领导", "主任", "教务", "督导", "书记", "党委" + "管理", "校长", "园长", "局长", "领导", "教务", "教导", "督导", "书记", "党委" }; - private static final String[] TEACHER_WORDS = {"教师", "老师", "班主任", "教工"}; + private static final String[] TEACHER_WORDS = {"教师", "老师", "班主任", "教工", "职工"}; private final AgentSettings settings; @@ -62,6 +70,13 @@ public class RoleResolver { public RoleResolver(AgentSettings settings) { this.settings = settings; + // ★ 启动时把「本次真正生效」的角色配置打出来:一旦部署环境存在配置漂移 + // (外部 application-prod.yml / 环境变量覆盖了 agent.roles),据此一眼可见。 + AgentSettings.Roles c = settings.getRoles(); + log.info("[角色配置] student={} teacher={} parent={} admin={} | type: student={} teacher={} admin={} parent={} | admin-also-teacher={}", + c.getStudent(), c.getTeacher(), c.getParent(), c.getAdmin(), + c.getStudentUserTypes(), c.getTeacherUserTypes(), c.getAdminUserTypes(), c.getParentUserTypes(), + c.isAdminAlsoTeacher()); } /** 解析用户角色集合(永不为空,至少含 GUEST) */ @@ -131,13 +146,23 @@ public class RoleResolver { return sb.toString(); } - /** 当前身份 → 智能体角色:角色号配置优先,角色名关键词兜底 */ + /** + * 当前身份 → 智能体角色。 + * + *

★ 先按 {@code roleName} 判定,再退回 {@code roleId}: + * 平台下发的 {@code roleName}(老师 / 校领导 / 学生 / 家长 / 局领导 / 工作号 / 管理员) + * 是平台自己的权威标签,与用户在门户里看到的一致;先认它, + * 可以免疫 {@code agent.roles.*} 配置漂移(部署环境里被旧的角色号配置覆盖)导致的身份误判。 + * 名称里看不出身份的(如「工作号」)再按角色号 {@code roleId} 映射。 + */ private Set matchCurrent(BoaRoleInfo current, AgentSettings.Roles cfg) { - Set hit = match(current.getRoleId(), cfg); - if (hit.isEmpty() && StringUtils.isNotBlank(current.getRoleName())) { - hit = matchByRoleName(current.getRoleName().trim()); + if (StringUtils.isNotBlank(current.getRoleName())) { + Set byName = matchByRoleName(current.getRoleName().trim()); + if (!byName.isEmpty()) { + return byName; + } } - return hit; + return match(current.getRoleId(), cfg); } /** 单个角色号 → 智能体角色(一个号理论上可命中多个分组,全部保留) */