🩹 登录建号租户改为优先取 Tenant-Id 请求头

接口契约要求 Tenant-Id 头 → tenant_id 参数 → 兜底 000000。
写库前仍兜到非空;入参与请求头不一致时以请求头为准。
同步订正两个 DTO 的 tenantId 说明。
This commit is contained in:
2026-10-23 16:34:10 +08:00
parent d28c8688cf
commit b04f68e168
3 changed files with 29 additions and 11 deletions
@@ -43,7 +43,7 @@ public class DriverEnsureProfileDTO implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
@Schema(description = "租户ID,为空时取当前登录租户;仍为空则拒绝写库")
@Schema(description = "租户ID,为空时取当前请求租户;仍为空则拒绝写库")
private String tenantId;
@Schema(description = "关联小程序用户ID(blade_mp_user.id)")
@@ -43,7 +43,7 @@ public class MpUserEnsureDTO implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
@Schema(description = "租户ID,为空时依次取当前登录租户与默认租户")
@Schema(description = "租户ID,为空时依次取 Tenant-Id 请求头与默认租户")
private String tenantId;
@Schema(description = "手机号")
@@ -24,6 +24,7 @@ package org.springblade.system.service.impl;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springblade.common.utils.PasswordRuleUtil;
@@ -35,6 +36,7 @@ import org.springblade.core.tool.utils.DateUtil;
import org.springblade.core.tool.utils.DigestUtil;
import org.springblade.core.tool.utils.Func;
import org.springblade.core.tool.utils.StringUtil;
import org.springblade.core.tool.utils.WebUtil;
import org.springblade.system.cache.MpUserCache;
import org.springblade.system.mapper.MpUserMapper;
import org.springblade.system.pojo.dto.MpUserEnsureDTO;
@@ -65,6 +67,11 @@ public class MpUserServiceImpl extends BaseServiceImpl<MpUserMapper, MpUser> imp
*/
private static final String DEFAULT_TENANT_ID = "000000";
/**
* 登录请求携带租户的请求头名
*/
private static final String TENANT_HEADER = "Tenant-Id";
@Override
public MpUser getByPhone(String tenantId, String phone) {
if (Func.isBlank(tenantId) || Func.isBlank(phone)) {
@@ -127,12 +134,12 @@ public class MpUserServiceImpl extends BaseServiceImpl<MpUserMapper, MpUser> imp
user.setStatus(1);
prepare(user);
validate(user);
// 登录路径不设密码:密码留空,避免调用方误传弱口令
// 登录路径不设密码,password 保持为空
user.setPassword(null);
try {
save(user);
} catch (Exception exception) {
// 并发建号撞 (tenant_id, phone) 唯一键:重读一次返回,登录方不该因重试失败
// 并发建号撞 (tenant_id, phone) 唯一键:重读一次并返回已有账号
MpUser concurrent = getByPhone(tenantId, phone);
if (concurrent != null && Func.isNotEmpty(concurrent.getId())) {
return concurrent;
@@ -148,15 +155,15 @@ public class MpUserServiceImpl extends BaseServiceImpl<MpUserMapper, MpUser> imp
}
/**
* 登录路径的租户解析:入参 → 当前登录租户 → 默认租户
* 登录路径的租户解析:Tenant-Id 头 → 入参 tenantId → 默认租户
* <p>
* 写库前必须得到非空值:唯一键 (tenant_id, phone) 对 NULL 不去重,租户为 NULL
* 会为同一手机号造出重复账号。
* 请求头与入参不一致时以请求头为准。写库前必须得到非空值:唯一键 (tenant_id, phone)
* 对 NULL 不去重,租户为 NULL 会为同一手机号造出重复账号。
*/
private String resolveEnsureTenantId(String tenantId) {
String resolved = trimToNull(tenantId);
String resolved = requestHeaderTenantId();
if (resolved == null) {
resolved = trimToNull(AuthUtil.getTenantId());
resolved = trimToNull(tenantId);
}
if (resolved == null) {
resolved = DEFAULT_TENANT_ID;
@@ -164,6 +171,17 @@ public class MpUserServiceImpl extends BaseServiceImpl<MpUserMapper, MpUser> imp
return resolved;
}
/**
* 当前请求头里的租户;无请求上下文时返回 null
*/
private String requestHeaderTenantId() {
HttpServletRequest request = WebUtil.getRequest();
if (request == null) {
return null;
}
return trimToNull(request.getHeader(TENANT_HEADER));
}
@Override
public MpUserInfo userInfo(Long userId) {
if (Func.isEmpty(userId)) {
@@ -319,8 +337,8 @@ public class MpUserServiceImpl extends BaseServiceImpl<MpUserMapper, MpUser> imp
if (!tenantId.equals(user.getTenantId())) {
throw new ServiceException("租户不匹配,无法绑定 openid");
}
// 目标账号已有另一个非空 openid 时不得覆盖:旧逻辑会静默顶掉上一个微信的绑定,
// 而一个微信换绑需要管理员确认,登录路径只放弃本次绑定(票 05)
// 目标账号已有另一个非空 openid 时不覆盖:一个微信换绑由管理员处理,
// 登录路径直接放弃本次绑定
if (Func.isNotBlank(user.getOpenid()) && !user.getOpenid().equals(openid)) {
log.warn("小程序用户已绑定其他 openid,跳过绑定:租户={} 账号={} 已有openid={} 本次openid={}",
tenantId, userId, user.getOpenid(), openid);