|
|
@ -71,8 +71,12 @@ public class AuthServiceImpl implements IAuthService { |
|
|
ThirdPartyAuthClient client = clientFactory.getClient(type); |
|
|
ThirdPartyAuthClient client = clientFactory.getClient(type); |
|
|
ThirdPartyUserInfo thirdUser = client.getUserInfo(authCode); |
|
|
ThirdPartyUserInfo thirdUser = client.getUserInfo(authCode); |
|
|
|
|
|
|
|
|
// 2~4. 数据库操作(事务保护,通过 self 调用走 AOP 代理)
|
|
|
// 2. 事务外组织准入预校验(ADR-0010):仅本地无匹配用户时触发。
|
|
|
AuthUser user = self.doLoginInTx(type, thirdUser, client); |
|
|
// 钉钉组织通讯录 HTTP 调用放在 DB 事务之外,避免首登洪峰长时间占用事务连接
|
|
|
|
|
|
preCheckOrgMembership(type, thirdUser, client); |
|
|
|
|
|
|
|
|
|
|
|
// 3. 数据库操作(事务保护,通过 self 调用走 AOP 代理)
|
|
|
|
|
|
AuthUser user = self.doLoginInTx(type, thirdUser); |
|
|
|
|
|
|
|
|
// 5. 签发 token(Redis 写入在 DB 事务之外,失败不影响 DB 数据)
|
|
|
// 5. 签发 token(Redis 写入在 DB 事务之外,失败不影响 DB 数据)
|
|
|
AuthLoginUser loginUser = new AuthLoginUser(); |
|
|
AuthLoginUser loginUser = new AuthLoginUser(); |
|
|
@ -92,8 +96,8 @@ public class AuthServiceImpl implements IAuthService { |
|
|
* DB 事务内的登录核心逻辑:定位用户 + 校验状态 + 刷新登录时间 |
|
|
* DB 事务内的登录核心逻辑:定位用户 + 校验状态 + 刷新登录时间 |
|
|
*/ |
|
|
*/ |
|
|
@Transactional(rollbackFor = Exception.class) |
|
|
@Transactional(rollbackFor = Exception.class) |
|
|
protected AuthUser doLoginInTx(IdentityTypeEnum type, ThirdPartyUserInfo thirdUser, ThirdPartyAuthClient client) { |
|
|
protected AuthUser doLoginInTx(IdentityTypeEnum type, ThirdPartyUserInfo thirdUser) { |
|
|
AuthUser user = resolveUser(type, thirdUser, client); |
|
|
AuthUser user = resolveUser(type, thirdUser); |
|
|
|
|
|
|
|
|
if (Boolean.FALSE.equals(user.getEnabled())) { |
|
|
if (Boolean.FALSE.equals(user.getEnabled())) { |
|
|
throw new BusinessErrorException(AuthConstants.CODE_USER_DISABLED, "账号已被禁用,请联系管理员"); |
|
|
throw new BusinessErrorException(AuthConstants.CODE_USER_DISABLED, "账号已被禁用,请联系管理员"); |
|
|
@ -107,9 +111,10 @@ public class AuthServiceImpl implements IAuthService { |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
/** |
|
|
/** |
|
|
* 定位本地用户:已绑定身份 -> 手机号匹配 -> 组织准入校验 -> 首登注册 |
|
|
* 定位本地用户:已绑定身份 -> 手机号匹配 -> 首登注册。 |
|
|
|
|
|
* <p>组织准入校验(ADR-0010)由 login() 在事务外预校验完成,本方法不再调钉钉 API。</p> |
|
|
*/ |
|
|
*/ |
|
|
private AuthUser resolveUser(IdentityTypeEnum type, ThirdPartyUserInfo thirdUser, ThirdPartyAuthClient client) { |
|
|
private AuthUser resolveUser(IdentityTypeEnum type, ThirdPartyUserInfo thirdUser) { |
|
|
// 2.1 该三方身份已绑定过,直接取对应用户
|
|
|
// 2.1 该三方身份已绑定过,直接取对应用户
|
|
|
AuthIdentity identity = authIdentityService.getByTypeAndUnionId(type, thirdUser.getUnionId()); |
|
|
AuthIdentity identity = authIdentityService.getByTypeAndUnionId(type, thirdUser.getUnionId()); |
|
|
if (identity != null) { |
|
|
if (identity != null) { |
|
|
@ -127,9 +132,8 @@ public class AuthServiceImpl implements IAuthService { |
|
|
user = authUserService.getByMobile(thirdUser.getMobile()); |
|
|
user = authUserService.getByMobile(thirdUser.getMobile()); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// 2.3 仍无匹配 -> 组织准入校验(ADR-0010)通过后首登自动注册
|
|
|
// 2.3 仍无匹配 -> 首登自动注册(组织准入已由 login() 的事务外预校验保证)
|
|
|
if (user == null) { |
|
|
if (user == null) { |
|
|
verifyOrgMembership(client, thirdUser); |
|
|
|
|
|
user = registerNewUser(thirdUser); |
|
|
user = registerNewUser(thirdUser); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@ -147,6 +151,33 @@ public class AuthServiceImpl implements IAuthService { |
|
|
return user; |
|
|
return user; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
* 事务外组织准入预校验(ADR-0010):本地已有匹配用户的登录不校验; |
|
|
|
|
|
* 仅本地查不到时调钉钉组织通讯录确认归属,HTTP 调用不占用 DB 事务连接。 |
|
|
|
|
|
* <p>事务内注册路径的组织门禁由此处保证(login() 是 doLoginInTx 的唯一入口)。</p> |
|
|
|
|
|
*/ |
|
|
|
|
|
private void preCheckOrgMembership(IdentityTypeEnum type, ThirdPartyUserInfo thirdUser, ThirdPartyAuthClient client) { |
|
|
|
|
|
if (hasLocalUser(type, thirdUser)) { |
|
|
|
|
|
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 中的用户不受影响。 |
|
|
* 组织准入校验(ADR-0010):非本组织成员拒绝登录。仅在首登注册前触发,已在 DB 中的用户不受影响。 |
|
|
*/ |
|
|
*/ |
|
|
|