From f0f70c6137cd84ca66f54f4de49ca98f23d32b7d Mon Sep 17 00:00:00 2001 From: luoweijian <1329394916@qq.com> Date: Tue, 4 Aug 2026 17:35:02 +0800 Subject: [PATCH] refactor(auth): deduplicate user location logic in login flow Extract locateUser() as the single source of truth for 'identity binding -> mobile match' resolution. Both preCheckOrgMembership (read-only probe) and resolveUser (login path) now share the same implementation, eliminating the risk of rule drift between the two call sites. Identity query is passed through to avoid redundant DB lookups. --- .../auth/service/impl/AuthServiceImpl.java | 74 +++++++++---------- 1 file changed, 37 insertions(+), 37 deletions(-) diff --git a/crm-auth/src/main/java/com/crm/auth/service/impl/AuthServiceImpl.java b/crm-auth/src/main/java/com/crm/auth/service/impl/AuthServiceImpl.java index 4346d4a..90e6670 100644 --- a/crm-auth/src/main/java/com/crm/auth/service/impl/AuthServiceImpl.java +++ b/crm-auth/src/main/java/com/crm/auth/service/impl/AuthServiceImpl.java @@ -115,33 +115,20 @@ public class AuthServiceImpl implements IAuthService { *

组织准入校验(ADR-0010)由 login() 在事务外预校验完成,本方法不再调钉钉 API。

*/ private AuthUser resolveUser(IdentityTypeEnum type, ThirdPartyUserInfo thirdUser) { - // 2.1 该三方身份已绑定过,直接取对应用户 + // 身份查询只做一次,供定位与绑定共用 AuthIdentity identity = authIdentityService.getByTypeAndUnionId(type, thirdUser.getUnionId()); - if (identity != null) { - AuthUser existUser = authUserService.getById(identity.getUserId()); - if (existUser != null) { - return existUser; - } - // 极端情况:身份存在但用户被物理删除,兜底走注册 - log.warn("身份绑定[{}]指向的用户[{}]不存在,将重新注册", identity.getId(), identity.getUserId()); - } - - // 2.2 按手机号匹配已有用户(跨平台身份合一的关键) - AuthUser user = null; - if (StrUtil.isNotBlank(thirdUser.getMobile())) { - user = authUserService.getByMobile(thirdUser.getMobile()); - } - - // 2.3 仍无匹配 -> 首登自动注册(组织准入已由 login() 的事务外预校验保证) + AuthUser user = locateUser(type, thirdUser, identity); + + // 仍无匹配 -> 首登自动注册(组织准入已由 login() 的事务外预校验保证) if (user == null) { user = registerNewUser(thirdUser); } - - // 2.4 处理身份绑定:孤儿身份重定向到新用户;无身份则新增 + + // 处理身份绑定:孤儿身份重定向到新用户;无身份则新增 if (identity == null) { authIdentityService.bind(user.getId(), type, thirdUser); - } else { - // 孤儿 identity:把原本指向已删除用户的绑定,重定向到本次定位到的用户,避免下次登录再次命中孤儿 + } else if (!identity.getUserId().equals(user.getId())) { + // 孤儿 Identity:把原本指向已删除用户的绑定,重定向到本次定位到的用户 AuthIdentity redirect = new AuthIdentity(); redirect.setId(identity.getId()); redirect.setUserId(user.getId()); @@ -150,6 +137,32 @@ public class AuthServiceImpl implements IAuthService { } return user; } + + /** + * 定位本地用户:已绑定身份 -> 手机号匹配。 + *

供 {@link #preCheckOrgMembership} 的只读探测和 {@link #resolveUser} 的登录定位共用, + * 确保「身份绑定 → 手机号匹配」的规则只写一遍,避免两处逻辑漂移。

+ * + * @param identity 已查询的身份绑定记录(可为 null),避免重复查询 + * @return 匹配到的用户;无匹配返回 null + */ + private AuthUser locateUser(IdentityTypeEnum type, ThirdPartyUserInfo thirdUser, AuthIdentity identity) { + // 1. 该三方身份已绑定过,直接取对应用户 + if (identity != null) { + AuthUser existUser = authUserService.getById(identity.getUserId()); + if (existUser != null) { + return existUser; + } + // 极端情况:身份存在但用户被物理删除,兜底走注册 + log.warn("身份绑定[{}]指向的用户[{}]不存在,将重新注册", identity.getId(), identity.getUserId()); + } + + // 2. 按手机号匹配已有用户(跨平台身份合一的关键) + if (StrUtil.isNotBlank(thirdUser.getMobile())) { + return authUserService.getByMobile(thirdUser.getMobile()); + } + return null; + } /** * 事务外组织准入预校验(ADR-0010):本地已有匹配用户的登录不校验; @@ -157,27 +170,14 @@ public class AuthServiceImpl implements IAuthService { *

事务内注册路径的组织门禁由此处保证(login() 是 doLoginInTx 的唯一入口)。

*/ private void preCheckOrgMembership(IdentityTypeEnum type, ThirdPartyUserInfo thirdUser, ThirdPartyAuthClient client) { - if (hasLocalUser(type, thirdUser)) { + // 只读探测:identity 查询一次,无缓存复用(事务外调用,与事务内 resolveUser 的查询独立) + AuthIdentity identity = authIdentityService.getByTypeAndUnionId(type, thirdUser.getUnionId()); + if (locateUser(type, thirdUser, identity) != null) { return; } verifyOrgMembership(client, thirdUser); } - /** - * 只读探测本地是否已有匹配用户(与 resolveUser 的定位规则一致,仅用于决定是否触发组织准入校验) - */ - private boolean hasLocalUser(IdentityTypeEnum type, ThirdPartyUserInfo thirdUser) { - AuthIdentity identity = authIdentityService.getByTypeAndUnionId(type, thirdUser.getUnionId()); - if (identity != null) { - AuthUser existUser = authUserService.getById(identity.getUserId()); - if (existUser != null) { - return true; - } - } - return StrUtil.isNotBlank(thirdUser.getMobile()) - && authUserService.getByMobile(thirdUser.getMobile()) != null; - } - /** * 组织准入校验(ADR-0010):非本组织成员拒绝登录。仅在首登注册前触发,已在 DB 中的用户不受影响。 */