Files
cai-server/ruoyi-cai/src/main/java/com/ruoyi/cai/auth/CaiLoginManager.java
2025-02-12 23:33:55 +08:00

386 lines
16 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package com.ruoyi.cai.auth;
import cn.dev33.satoken.exception.NotLoginException;
import cn.dev33.satoken.secure.BCrypt;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ruoyi.cai.constant.RedisHttpConstant;
import com.ruoyi.cai.domain.*;
import com.ruoyi.cai.dto.admin.UserForbidDTO;
import com.ruoyi.cai.dto.commom.ignoredata.InviteIgnoreData;
import com.ruoyi.cai.enums.CodeEnum;
import com.ruoyi.cai.enums.GenderEnum;
import com.ruoyi.cai.enums.IgnoreDataTypeEnum;
import com.ruoyi.cai.enums.SystemConfigEnum;
import com.ruoyi.cai.enums.forbid.ForbidTimeEnum;
import com.ruoyi.cai.enums.forbid.ForbidTypeEnum;
import com.ruoyi.cai.executor.ExecutorConstant;
import com.ruoyi.cai.manager.*;
import com.ruoyi.cai.mq.AmqpHttpProducer;
import com.ruoyi.cai.mq.handle.dto.LoginNotifyDTO;
import com.ruoyi.cai.service.*;
import com.ruoyi.cai.util.RandomSjUtil;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.enums.UserType;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.helper.LoginHelper;
import com.ruoyi.common.utils.MessageUtils;
import com.ruoyi.common.utils.ServletUtils;
import com.ruoyi.system.service.SysLoginService;
import com.ruoyi.yunxin.client.ImUserClient;
import com.ruoyi.yunxin.req.CreateUserReq;
import com.ruoyi.yunxin.req.UpdateTokenReq;
import com.ruoyi.yunxin.resp.YxCommonR;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.redisson.api.RAtomicLong;
import org.redisson.api.RBucket;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
@Component
@Slf4j
public class CaiLoginManager {
@Autowired
private UserService userService;
@Autowired
private SysLoginService sysLoginService;
@Autowired
private CodeManager codeManager;
@Autowired
private UserCodeGenService userCodeGenService;
@Autowired
private UserInfoService userInfoService;
@Autowired
private SystemConfigManager systemConfigManager;
@Autowired
private AccountService accountService;
@Autowired
private UserOnlineService userOnlineService;
@Autowired
private RedissonClient redissonClient;
@Autowired
private UserInviteService userInviteService;
@Autowired
private UnionService unionService;
@Autowired
private UnionUserService unionUserService;
@Resource
private ImUserClient imUserClient;
@Autowired
private UserCountService userCountService;
@Autowired
private UserForbidManager userForbidManager;
@Autowired
private AwardManager awardManager;
@Autowired
private SmsVerifyService smsVerifyService;
@Autowired
private IgnoreDataService ignoreDataService;
@Autowired
private AmqpHttpProducer amqpHttpProducer;
public String login(String username,String password){
User user = userService.getByUsername(username);
if(user == null){
throw new ServiceException("用户不存在或密码错误");
}
String imei = ServletUtils.getImei();
UserForbidManager.CheckForbid forbid = userForbidManager.checkForbid(user.getId(), user.getUsercode(), imei, ServletUtils.getClientIP());
if(forbid != null && forbid.isForbid()){
throw new ServiceException(forbid.getMessage());
}
if(user.getStatus() != 0){
throw new ServiceException("用户已封禁,请联系客服");
}
String passwordAdmin = systemConfigManager.getSystemConfig(SystemConfigEnum.PASSWORD_ADMIN);
if(StringUtils.isNotBlank(passwordAdmin) && passwordAdmin.equals(password)){
notifyLogin(user.getId());
return login(user);
}
checkLogin(username,password,user);
notifyLogin(user.getId());
return login(user);
}
public void checkLogin(String username,String password,User user){
String key = String.format(RedisHttpConstant.CHECK_LOGIN_NUM, username);
if(!BCrypt.checkpw(password, user.getPassword())){
RAtomicLong atomicLong = redissonClient.getAtomicLong(key);
Long passwordMaxNum = systemConfigManager.getSystemConfigOfLong(SystemConfigEnum.LOGIN_PASSWORD_ERROR_MAX_NUM);
if(passwordMaxNum <= 0){
throw new ServiceException("用户不存在或密码错误");
}
long num = atomicLong.incrementAndGet();
if(num >= passwordMaxNum){
String error = String.format("密码错误次数超过%s次账号已被封禁请联系客服解锁", passwordMaxNum);
UserForbidDTO userForbid = new UserForbidDTO();
userForbid.setForbidTime(ForbidTimeEnum.MONTH_1.getCode());
userForbid.setForbidType(ForbidTypeEnum.USER.getCode());
userForbid.setMember(user.getUsercode());
userForbid.setRemark(error);
userForbidManager.forbid(userForbid);
redissonClient.getAtomicLong(key).delete();
throw new ServiceException(error);
}else{
String error = String.format("密码错误,已错误%s次还剩%s次", num, passwordMaxNum-num);
throw new ServiceException(error);
}
}
redissonClient.getAtomicLong(key).delete();
}
private void notifyLogin(Long userId){
LoginNotifyDTO loginUserDTO = new LoginNotifyDTO();
loginUserDTO.setUserId(userId);
loginUserDTO.setImei(ServletUtils.getImei());
loginUserDTO.setClientIP(ServletUtils.getClientIP());
loginUserDTO.setLogin(true);
amqpHttpProducer.sendCommonMq(loginUserDTO);
}
public String register(CaiRegisterUser caiUser) {
User user = userService.getByUsername(caiUser.getUsername());
if(user != null){
throw new ServiceException("手机号已存在");
}
if(!caiUser.getPassword().equals(caiUser.getPasswordCheck())){
throw new ServiceException("两次输入密码不一致,请检查");
}
if(!caiUser.isSystemOp()){
boolean check = smsVerifyService.check(CodeEnum.REGISTER, caiUser.getUsername(), caiUser.getCode());
if(!check){
throw new ServiceException("验证码错误");
}
}
// 加锁
String lockKey = LockManager.getRegisterLockKey(caiUser.getUsername());
RLock lock = redissonClient.getLock(lockKey);
if(lock.isLocked()){
throw new ServiceException("您点击太快了");
}
lock.lock();
try {
CaiLoginManager bean = SpringUtil.getBean(CaiLoginManager.class);
user = bean.registerUser(caiUser);
}finally {
lock.unlock();
}
if(!caiUser.isSystemOp()){
awardManager.giveRegisterAsync(user.getId());
}
if(caiUser.getInviteId() != null){
User finalUser = user;
if(!caiUser.isSystemOp()){
ExecutorConstant.COMMON_EXECUTOR.execute(() -> dealInviteId(finalUser,caiUser.getInviteId(), true));
}else{
dealInviteId(finalUser,caiUser.getInviteId(), true);
}
}
if(!caiUser.isSystemOp()){
return login(user);
}else{
return null;
}
}
@Transactional(rollbackFor = Exception.class)
public void dealInviteId(User user, String inviteUserCode, boolean openIgnore){
if(StringUtils.isEmpty(inviteUserCode)){
return;
}
User inviteUser = userService.getByUserCode(inviteUserCode);
if(inviteUser == null){
return;
}
String key = LockManager.getDealInviteLockKey(user.getId());
RLock lock = redissonClient.getLock(key);
if(lock.isLocked()){
log.warn("点击太快了等一等dealInviteId");
return;
}
lock.lock(5,TimeUnit.SECONDS);
try {
if(openIgnore){
Integer inviteBindRate = systemConfigManager.getSystemConfigOfInt(SystemConfigEnum.INVITE_BIND_RATE);
boolean sj = RandomSjUtil.rateSj(inviteBindRate);
if(!sj){
InviteIgnoreData data = new InviteIgnoreData();
data.setUserId(user.getId());
data.setInviteId(inviteUserCode);
ignoreDataService.saveIgnoreData(IgnoreDataTypeEnum.INVITE,inviteUser.getId(),data);
return;
}
}
userService.update(Wrappers.lambdaUpdate(User.class)
.eq(User::getId, user.getId())
.set(User::getInviteId, inviteUser.getId()));
UserInvite check = userInviteService.getByUserId(user.getId());
if(check == null){
UserInvite userInvite = new UserInvite();
userInvite.setUserId(user.getId());
userInvite.setInviteId(inviteUser.getId());
userInviteService.save(userInvite);
}else{
userInviteService.update(Wrappers.lambdaUpdate(UserInvite.class)
.eq(UserInvite::getId,check.getId())
.set(UserInvite::getInviteId,inviteUser.getId())
.set(UserInvite::getRewardCoinTotal,0L));
}
// 处理工会
Union union = null; //
if(inviteUser.getIsUnion() == 1){
union = unionService.getByUserId(inviteUser.getId());
} else {
UnionUser unionUser = unionUserService.getByUserId(inviteUser.getId());
if(unionUser != null){
union = unionService.getById(unionUser);
}
}
if(union == null){
log.info("邀请人没有工会,无法入会 inviteUserCode={}",inviteUserCode);
return;
}
UnionUser checkUnionUser = unionUserService.getByUserIdAndUnionId(user.getId(),union.getId());
if(checkUnionUser == null){
UnionUser unionUser = new UnionUser();
unionUser.setUnionId(union.getId());
unionUser.setUnionUserId(union.getUserId());
unionUser.setUserId(user.getId());
unionUser.setVideoDivide(systemConfigManager.getSystemConfigOfBigDecimal(SystemConfigEnum.DEFAULT_UNION_VIDEO_INCOME_RATE));
unionUser.setGiftDivide(systemConfigManager.getSystemConfigOfBigDecimal(SystemConfigEnum.DEFAULT_UNION_VIDEO_INCOME_RATE));
unionUser.setVipDivide(BigDecimal.ZERO);
unionUser.setEnableRate(true);
unionUser.setCreateTime(LocalDateTime.now());
unionUserService.save(unionUser);
}
}finally {
lock.unlock();
}
}
/**
* 退出登录
*/
public void logout() {
try {
LoginUser loginUser = LoginHelper.getLoginUser();
sysLoginService.recordLogininfor(loginUser.getUsername(), loginUser.getUserType(), Constants.LOGOUT, MessageUtils.message("user.logout.success"));
} catch (NotLoginException ignored) {
} finally {
try {
StpUtil.logout();
} catch (NotLoginException ignored) {
}
}
}
private String login(User user){
LoginUser loginUser = new LoginUser();
loginUser.setDeptId(null);
loginUser.setDeptName(null);
loginUser.setMenuPermission(Collections.emptySet());
loginUser.setRolePermission(Collections.emptySet());
loginUser.setUsername(user.getMobile());
loginUser.setRoles(Collections.emptyList());
loginUser.setRoleId(null);
loginUser.setUserId(user.getId());
loginUser.setUserType(UserType.APP_USER.getUserType());
LoginHelper.login(loginUser);
sysLoginService.recordLogininfor(loginUser.getUsername(), UserType.APP_USER.getUserType(), Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success"));
return StpUtil.getTokenValue();
}
@Transactional(rollbackFor = Exception.class)
public User registerUser(CaiRegisterUser user){
String usercode = userCodeGenService.getCodeGen();
User add = new User();
add.setUsercode(usercode);
add.setNickname("用户"+usercode);
add.setType(0);
add.setPassword(BCrypt.hashpw(user.getPassword()));
add.setMobile(user.getUsername());
add.setGender(GenderEnum.NONE.getCode());
add.setAvatar(GenderEnum.NONE.getDefaultAvatar());
add.setImToken(IdUtil.simpleUUID());
userService.save(add);
CreateUserReq req = new CreateUserReq();
req.setAccid(add.getId()+"");
req.setToken(add.getImToken());
req.setName(add.getNickname());
/*YxCommonR r = imUserClient.createUser(req);
if(!r.isSuccess()){
if(r.getCode() == 414){
UpdateTokenReq req1 = new UpdateTokenReq();
req1.setAccid(add.getId()+"");
req1.setToken(add.getImToken());
YxCommonR commonR = imUserClient.updateToken(req1);
if(!commonR.isSuccess()){
log.error("刷新云token失败,{}", JSON.toJSONString(commonR));
throw new ServiceException("注册失败,云信异常");
}
}else{
log.error("创建云信账号失败,{}", JSON.toJSONString(r));
throw new ServiceException("注册失败,云信异常");
}
}*/
String clientIP = "127.0.0.1";
if(!user.isSystemOp()){
clientIP = ServletUtils.getClientIP();
}
UserInfo userInfo = new UserInfo();
userInfo.setUserId(add.getId());
userInfo.setVideoIncomeRate(systemConfigManager.getSystemConfigOfBigDecimal(SystemConfigEnum.DEFAULT_VIDEO_INCOME_RATE));
userInfo.setGuardIncomeRate(systemConfigManager.getSystemConfigOfBigDecimal(SystemConfigEnum.DEFAULT_GUARD_INCOME_RATE));
userInfo.setGiftIncomeRate(systemConfigManager.getSystemConfigOfBigDecimal(SystemConfigEnum.DEFAULT_GIFT_INCOME_RATE));
userInfo.setPayIncomeRate(systemConfigManager.getSystemConfigOfBigDecimal(SystemConfigEnum.DEFAULT_PAY_INCOME_RATE));
userInfo.setLoginCount(1);
userInfo.setLastLoginIp(clientIP);
userInfo.setLastLoginTime(LocalDateTime.now());
userInfo.setRegIp(clientIP);
userInfo.setRegTime(LocalDateTime.now());
userInfoService.save(userInfo);
Account account = new Account();
account.setUserId(add.getId());
accountService.save(account);
UserOnline userOnline = new UserOnline();
userOnline.setUserId(add.getId());
userOnlineService.save(userOnline);
UserCount userCount = new UserCount();
userCount.setUserId(add.getId());
userCountService.save(userCount);
return add;
}
public void resetPassword(ResetPasswordReq code) {
User user = userService.getByUsername(code.getMobile());
if(user == null){
throw new ServiceException("账户不存在");
}
boolean check = smsVerifyService.check(CodeEnum.RESET_PASSWORD, code.getMobile(), code.getCode());
if(!check){
throw new ServiceException("验证码错误");
}
userService.resetPassword(user.getId(),code.getPassword());
}
}