♻️ 微信与短信登录改走MpLoginSupport自动建号建档
This commit is contained in:
@@ -27,6 +27,7 @@ package org.springblade.auth.granter;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import org.springblade.auth.constant.BladeAuthConstant;
|
||||
import org.springblade.auth.service.MpLoginSupport;
|
||||
import org.springblade.core.oauth2.constant.OAuth2TokenConstant;
|
||||
import org.springblade.core.oauth2.exception.UserInvalidException;
|
||||
import org.springblade.core.oauth2.granter.AbstractTokenGranter;
|
||||
@@ -43,10 +44,15 @@ import org.springblade.core.tool.utils.SM2Util;
|
||||
import org.springblade.core.tool.utils.StringUtil;
|
||||
import org.springblade.core.tool.utils.WebUtil;
|
||||
import org.springblade.resource.feign.ISmsClient;
|
||||
import org.springblade.system.pojo.enums.MpUserIdentity;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* SmsTokenGranter
|
||||
* <p>
|
||||
* 除验证码校验外,还要按请求来源分流:小程序(User-Type: mp)登录时账号不存在要自动建,
|
||||
* Web 短信登录保持原样不建号。建号逻辑不能下沉到 {@code BladeUserDetailService.loadByPhone},
|
||||
* 那条方法还被「发送短信验证码」复用,会在发码时就建出账号(刷号)。
|
||||
*
|
||||
* @author BladeX
|
||||
*/
|
||||
@@ -56,12 +62,14 @@ public class SmsTokenGranter extends AbstractTokenGranter {
|
||||
private final OAuth2UserService userService;
|
||||
private final ISmsClient smsClient;
|
||||
private final OAuth2Properties properties;
|
||||
private final MpLoginSupport mpLoginSupport;
|
||||
|
||||
public SmsTokenGranter(OAuth2ClientService clientService, OAuth2UserService userService, PasswordHandler passwordHandler, ISmsClient smsClient, OAuth2Properties properties) {
|
||||
public SmsTokenGranter(OAuth2ClientService clientService, OAuth2UserService userService, PasswordHandler passwordHandler, ISmsClient smsClient, OAuth2Properties properties, MpLoginSupport mpLoginSupport) {
|
||||
super(clientService, userService, passwordHandler);
|
||||
this.userService = userService;
|
||||
this.smsClient = smsClient;
|
||||
this.properties = properties;
|
||||
this.mpLoginSupport = mpLoginSupport;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -86,8 +94,10 @@ public class SmsTokenGranter extends AbstractTokenGranter {
|
||||
if (!result.isSuccess()) {
|
||||
throw new UserInvalidException(OAuth2TokenConstant.CAPTCHA_NOT_CORRECT);
|
||||
}
|
||||
// 获取用户信息
|
||||
OAuth2User user = userService.loadByPhone(decryptedPhone, request);
|
||||
// 获取用户信息:只有小程序登录才允许自动建号,Web 短信登录仍走原查询
|
||||
OAuth2User user = isMpLoginRequest(request)
|
||||
? mpLoginSupport.ensureLoginAccount(tenantId, decryptedPhone, null)
|
||||
: userService.loadByPhone(decryptedPhone, request);
|
||||
// 校验用户信息
|
||||
if (!userService.validateUser(user)) {
|
||||
throw new UserInvalidException(OAuth2TokenConstant.TOKEN_NOT_CORRECT);
|
||||
@@ -97,6 +107,13 @@ public class SmsTokenGranter extends AbstractTokenGranter {
|
||||
return user;
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否小程序登录:请求头 User-Type=mp(Web 与小程序共用客户端,不能按 clientId 分流)
|
||||
*/
|
||||
private boolean isMpLoginRequest(OAuth2Request request) {
|
||||
return request != null && MpUserIdentity.DETAIL_TYPE.equalsIgnoreCase(Func.toStr(request.getUserType()));
|
||||
}
|
||||
|
||||
private SmsCode buildSmsCode() {
|
||||
HttpServletRequest request = WebUtil.getRequest();
|
||||
return new SmsCode().setId(request.getParameter("id"))
|
||||
|
||||
@@ -2,7 +2,7 @@ package org.springblade.auth.granter;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springblade.auth.utils.TokenUtil;
|
||||
import org.springblade.auth.service.MpLoginSupport;
|
||||
import org.springblade.core.oauth2.exception.UserInvalidException;
|
||||
import org.springblade.core.oauth2.granter.AbstractTokenGranter;
|
||||
import org.springblade.core.oauth2.handler.PasswordHandler;
|
||||
@@ -11,12 +11,9 @@ import org.springblade.core.oauth2.service.OAuth2Client;
|
||||
import org.springblade.core.oauth2.service.OAuth2ClientService;
|
||||
import org.springblade.core.oauth2.service.OAuth2User;
|
||||
import org.springblade.core.oauth2.service.OAuth2UserService;
|
||||
import org.springblade.core.tool.api.R;
|
||||
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.feign.IMpUserClient;
|
||||
import org.springblade.system.pojo.entity.MpUserInfo;
|
||||
import org.springblade.thirdparty.wechat.constant.WechatMiniConstant;
|
||||
import org.springblade.thirdparty.wechat.exception.WechatMiniException;
|
||||
import org.springblade.thirdparty.wechat.pojo.vo.WechatPhoneVO;
|
||||
@@ -28,8 +25,8 @@ import org.springframework.stereotype.Component;
|
||||
* 微信小程序手机号一键登录。
|
||||
* <p>
|
||||
* grant_type=wechat_applet,参数:loginCode(wx.login)、phoneCode(getPhoneNumber)。
|
||||
* 流程:换 openid + 手机号 → 按手机号查小程序用户(blade_mp_user,不存在则拒绝)
|
||||
* → 记录 openid → 按身份发令牌(不依赖系统角色)。
|
||||
* 流程:换 openid + 手机号 → 由 {@link MpLoginSupport} 找到或创建账号并补齐档案
|
||||
* → 按身份发令牌(不依赖系统角色)。
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
@@ -37,17 +34,17 @@ public class WechatMiniTokenGranter extends AbstractTokenGranter {
|
||||
|
||||
private final OAuth2UserService userService;
|
||||
private final IWechatMiniService wechatMiniService;
|
||||
private final IMpUserClient mpUserClient;
|
||||
private final MpLoginSupport mpLoginSupport;
|
||||
|
||||
public WechatMiniTokenGranter(OAuth2ClientService clientService,
|
||||
OAuth2UserService userService,
|
||||
PasswordHandler passwordHandler,
|
||||
IWechatMiniService wechatMiniService,
|
||||
IMpUserClient mpUserClient) {
|
||||
MpLoginSupport mpLoginSupport) {
|
||||
super(clientService, userService, passwordHandler);
|
||||
this.userService = userService;
|
||||
this.wechatMiniService = wechatMiniService;
|
||||
this.mpUserClient = mpUserClient;
|
||||
this.mpLoginSupport = mpLoginSupport;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -82,28 +79,12 @@ public class WechatMiniTokenGranter extends AbstractTokenGranter {
|
||||
throw new UserInvalidException("未获取到微信手机号");
|
||||
}
|
||||
|
||||
R<MpUserInfo> mpUserResult = mpUserClient.userInfoByPhone(request.getTenantId(), phone);
|
||||
if (mpUserResult == null || !mpUserResult.isSuccess() || mpUserResult.getData() == null
|
||||
|| mpUserResult.getData().getUser() == null) {
|
||||
throw new UserInvalidException("用户不存在,无法登录");
|
||||
}
|
||||
|
||||
OAuth2User user = TokenUtil.convertMpUser(mpUserResult.getData());
|
||||
// 账号不存在时自动建号,建档与绑 openid 由编排层尽力而为,失败不阻断登录
|
||||
OAuth2User user = mpLoginSupport.ensureLoginAccount(request.getTenantId(), phone, session.getOpenid());
|
||||
if (!userService.validateUser(user)) {
|
||||
throw new UserInvalidException("用户身份无效,无法登录");
|
||||
}
|
||||
|
||||
R<Boolean> bindResult = mpUserClient.bindOpenId(
|
||||
request.getTenantId(),
|
||||
Func.toLong(user.getUserId()),
|
||||
session.getOpenid()
|
||||
);
|
||||
if (bindResult == null || !bindResult.isSuccess()) {
|
||||
String msg = bindResult != null ? bindResult.getMsg() : "绑定 openid 失败";
|
||||
log.warn("绑定微信 openid 失败 userId={} openid={} msg={}", user.getUserId(), session.getOpenid(), msg);
|
||||
throw new UserInvalidException(StringUtil.isBlank(msg) ? "绑定 openid 失败" : msg);
|
||||
}
|
||||
|
||||
user.setClient(oauthClient);
|
||||
return user;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user