修改小程序登录逻辑
This commit is contained in:
@@ -4,6 +4,7 @@ import javax.annotation.Resource;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import com.ruoyi.cms.domain.vo.WechatAuthVO;
|
||||
import com.ruoyi.cms.service.IAppUserService;
|
||||
import com.ruoyi.cms.util.StringUtil;
|
||||
import com.ruoyi.cms.util.WechatUtil;
|
||||
@@ -12,6 +13,7 @@ import com.ruoyi.common.core.domain.entity.AppUser;
|
||||
import com.ruoyi.common.core.domain.model.LoginBody;
|
||||
import com.ruoyi.common.core.domain.model.LoginSiteUser;
|
||||
import com.ruoyi.common.core.domain.model.RegisterBody;
|
||||
import com.ruoyi.common.core.redis.DistributedLockUtil;
|
||||
import com.ruoyi.common.utils.*;
|
||||
import com.ruoyi.framework.web.exception.ParamErrorConstants;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@@ -69,6 +71,9 @@ public class SysLoginService
|
||||
WechatUtil wechatUtil;
|
||||
@Autowired
|
||||
private IAppUserService appUserService;
|
||||
@Autowired
|
||||
private DistributedLockUtil distributedLockUtil;
|
||||
|
||||
/**
|
||||
* 登录验证
|
||||
*
|
||||
@@ -258,7 +263,7 @@ public class SysLoginService
|
||||
return AjaxResult.error("微信授权失败");
|
||||
}
|
||||
//验证是否登录过
|
||||
AppUser existingUser=appUserService.selectByOpenid(openid);
|
||||
AppUser existingUser=appUserService.selectByOpenid(openid,dto.getUserType());
|
||||
if(existingUser!=null){
|
||||
if(StringUtils.isEmpty(existingUser.getIsCompanyUser())){
|
||||
updateAppUserCommon(existingUser,openid,unionid,dto.getUserType());
|
||||
@@ -316,44 +321,37 @@ public class SysLoginService
|
||||
* 小程序登录主逻辑
|
||||
*/
|
||||
public AjaxResult appLoginNew(LoginBody dto) {
|
||||
AjaxResult validateResult = validateLoginParam(dto, false);
|
||||
//1.验证基础参数
|
||||
AjaxResult validateResult = validateBaseParam(dto);
|
||||
if (validateResult != null) {
|
||||
return validateResult;
|
||||
}
|
||||
|
||||
try {
|
||||
JSONObject sessionInfo = wechatUtil.code2Session(dto.getCode());
|
||||
String openid = sessionInfo.getString("openid");
|
||||
String unionid = sessionInfo.getString("unionid");
|
||||
String sessionKey = sessionInfo.getString("session_key");
|
||||
|
||||
if (openid == null) {
|
||||
//2. 微信授权获取OpenID/UnionID/SessionKey
|
||||
WechatAuthVO wechatAuthVO = getWechatAuthInfo(dto.getCode());
|
||||
if (wechatAuthVO == null) {
|
||||
return AjaxResult.error("微信授权失败");
|
||||
}
|
||||
String openid = wechatAuthVO.getOpenid();
|
||||
String unionid = wechatAuthVO.getUnionid();
|
||||
String sessionKey = wechatAuthVO.getSessionKey();
|
||||
|
||||
AppUser existingUser = appUserService.selectByOpenid(openid);
|
||||
String userType = dto.getUserType();
|
||||
//3. 优先匹配「OpenID+角色」的老用户
|
||||
AppUser existingUser = appUserService.selectByOpenid(openid,userType);
|
||||
if (existingUser != null) {
|
||||
return handleExistingUser(existingUser, dto.getUserType());
|
||||
return handleExistingUser(existingUser, userType);
|
||||
}
|
||||
|
||||
validateResult = validateLoginParam(dto, true);
|
||||
if (validateResult != null) {
|
||||
return validateResult;
|
||||
}
|
||||
|
||||
JSONObject phoneInfo = wechatUtil.decryptPhoneNumber(dto.getEncryptedData(), sessionKey, dto.getIv());
|
||||
String phone = phoneInfo.getString("phoneNumber");
|
||||
|
||||
// 4. 解密获取手机号(含二次校验)
|
||||
String phone = decryptPhone(dto, sessionKey);
|
||||
if (phone == null) {
|
||||
return AjaxResult.error("获取手机号失败");
|
||||
}
|
||||
|
||||
AppUser phoneUser = appUserService.getPhone(phone);
|
||||
if (phoneUser != null) {
|
||||
return handlePhoneBoundUser(phoneUser, openid, unionid, dto.getUserType());
|
||||
} else {
|
||||
return handleNewUser(openid, unionid, phone, dto.getUserType());
|
||||
}
|
||||
// 5. 处理用户匹配与注册(核心逻辑拆分到独立方法)
|
||||
return handleUserMatchAndRegister(openid, unionid, phone, userType);
|
||||
} catch (Exception e) {
|
||||
System.err.println("登录失败:" + e.getMessage());
|
||||
return AjaxResult.error("登录失败,请稍后重试");
|
||||
@@ -361,9 +359,11 @@ public class SysLoginService
|
||||
}
|
||||
|
||||
/**
|
||||
* 参数校验方法(仅返回错误信息,补充userType校验)
|
||||
* 1-基础参数校验(原validateLoginParam false场景)
|
||||
* @param dto
|
||||
* @return
|
||||
*/
|
||||
private AjaxResult validateLoginParam(LoginBody dto, boolean needDecryptPhone) {
|
||||
private AjaxResult validateBaseParam(LoginBody dto) {
|
||||
if (dto == null) {
|
||||
return AjaxResult.error(ParamErrorConstants.PARAM_NULL_MSG);
|
||||
}
|
||||
@@ -376,17 +376,134 @@ public class SysLoginService
|
||||
!StringUtil.IS_JOB_REQUEST_USER.equals(userType)) {
|
||||
return AjaxResult.error(ParamErrorConstants.USER_TYPE_INVALID_MSG);
|
||||
}
|
||||
if (needDecryptPhone) {
|
||||
if (StringUtils.isEmpty(dto.getEncryptedData())) {
|
||||
return AjaxResult.error(ParamErrorConstants.ENCRYPTED_DATA_EMPTY_MSG);
|
||||
}
|
||||
if (StringUtils.isEmpty(dto.getIv())) {
|
||||
return AjaxResult.error(ParamErrorConstants.IV_EMPTY_MSG);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 2-微信授权信息获取(封装code2Session逻辑)
|
||||
* @param code
|
||||
* @return
|
||||
*/
|
||||
private WechatAuthVO getWechatAuthInfo(String code) {
|
||||
JSONObject sessionInfo = wechatUtil.code2Session(code);
|
||||
if (sessionInfo == null || sessionInfo.getString("openid") == null) {
|
||||
return null;
|
||||
}
|
||||
WechatAuthVO authVO = new WechatAuthVO();
|
||||
authVO.setOpenid(sessionInfo.getString("openid"));
|
||||
authVO.setUnionid(StringUtils.isBlank(sessionInfo.getString("unionid")) ? "" : sessionInfo.getString("unionid"));
|
||||
authVO.setSessionKey(sessionInfo.getString("session_key"));
|
||||
return authVO;
|
||||
}
|
||||
|
||||
/**
|
||||
* 3-手机号解密(含二次参数校验)
|
||||
* @param dto
|
||||
* @param sessionKey
|
||||
* @return
|
||||
*/
|
||||
private String decryptPhone(LoginBody dto, String sessionKey) {
|
||||
// 二次校验(解密相关参数)
|
||||
AjaxResult validateResult = validateDecryptParam(dto);
|
||||
if (validateResult != null) {
|
||||
return null;
|
||||
}
|
||||
// 解密手机号
|
||||
JSONObject phoneInfo = wechatUtil.decryptPhoneNumber(dto.getEncryptedData(), sessionKey, dto.getIv());
|
||||
String phone = phoneInfo.getString("phoneNumber");
|
||||
if (phone == null || phone.trim().isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
return phone.trim();
|
||||
}
|
||||
|
||||
/**
|
||||
* 4-解密参数校验(原validateLoginParam true场景)
|
||||
* @param dto
|
||||
* @return
|
||||
*/
|
||||
private AjaxResult validateDecryptParam(LoginBody dto) {
|
||||
if (StringUtils.isEmpty(dto.getEncryptedData())) {
|
||||
return AjaxResult.error(ParamErrorConstants.ENCRYPTED_DATA_EMPTY_MSG);
|
||||
}
|
||||
if (StringUtils.isEmpty(dto.getIv())) {
|
||||
return AjaxResult.error(ParamErrorConstants.IV_EMPTY_MSG);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 5-用户匹配与注册(含锁逻辑、无角色数据处理)
|
||||
* @param openid
|
||||
* @param unionid
|
||||
* @param phone
|
||||
* @param userType
|
||||
* @return
|
||||
*/
|
||||
private AjaxResult handleUserMatchAndRegister(String openid, String unionid, String phone, String userType) {
|
||||
// 匹配「手机号+角色」的用户
|
||||
AppUser phoneRoleUser = appUserService.getPhoneAndUserType(phone, userType);
|
||||
if (phoneRoleUser != null) {
|
||||
return handlePhoneBoundUser(phoneRoleUser, openid, unionid, userType);
|
||||
}
|
||||
|
||||
// 匹配无角色历史数据
|
||||
AppUser noRoleUser = appUserService.getPhoneAndNoRole(phone);
|
||||
if (noRoleUser != null) {
|
||||
return handleNoRoleUserBinding(openid, unionid, phone, userType, noRoleUser);
|
||||
}
|
||||
|
||||
// 全新用户注册
|
||||
return handleNewUserRegistration(openid, unionid, phone, userType);
|
||||
}
|
||||
|
||||
/**
|
||||
* 6-无角色用户绑定(含分布式锁)
|
||||
* @param openid
|
||||
* @param unionid
|
||||
* @param phone
|
||||
* @param userType
|
||||
* @param noRoleUser
|
||||
* @return
|
||||
*/
|
||||
private AjaxResult handleNoRoleUserBinding(String openid, String unionid, String phone, String userType, AppUser noRoleUser) {
|
||||
String lockKey = "login_no_role_bind_" + phone + "_" + userType;
|
||||
try (DistributedLockUtil.AutoReleaseLock lock = distributedLockUtil.tryLock(lockKey)) {
|
||||
if (!lock.isLocked()) {
|
||||
return AjaxResult.error("登录请求过于频繁,请稍后重试");
|
||||
}
|
||||
// 双重检查
|
||||
AppUser doubleCheck = appUserService.getPhoneAndUserType(phone, userType);
|
||||
if (doubleCheck != null) {
|
||||
return handlePhoneBoundUser(doubleCheck, openid, unionid, userType);
|
||||
}
|
||||
return handlePhoneBoundUser(noRoleUser, openid, unionid, userType);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 7-新用户注册(含分布式锁)
|
||||
* @param openid
|
||||
* @param unionid
|
||||
* @param phone
|
||||
* @param userType
|
||||
* @return
|
||||
*/
|
||||
private AjaxResult handleNewUserRegistration(String openid, String unionid, String phone, String userType) {
|
||||
String createLockKey = "login_create_" + phone + "_" + userType;
|
||||
try (DistributedLockUtil.AutoReleaseLock lock = distributedLockUtil.tryLock(createLockKey)) {
|
||||
if (!lock.isLocked()) {
|
||||
return AjaxResult.error("登录请求过于频繁,请稍后重试");
|
||||
}
|
||||
// 双重检查
|
||||
AppUser checkNew = appUserService.getPhoneAndUserType(phone, userType);
|
||||
if (checkNew != null) {
|
||||
return handlePhoneBoundUser(checkNew, openid, unionid, userType);
|
||||
}
|
||||
return handleNewUser(openid, unionid, phone, userType);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理老用户登录(日志用println)
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user