|
@@ -0,0 +1,270 @@
|
|
|
+package com.rongwei.zhsw.code.service.impl;
|
|
|
+
|
|
|
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
|
|
+import com.rongwei.commonservice.service.RedisService;
|
|
|
+
|
|
|
+import com.rongwei.rwadmincommon.system.domain.SysUserDo;
|
|
|
+import com.rongwei.rwadmincommon.system.domain.UserLoginVo;
|
|
|
+import com.rongwei.rwadmincommon.system.service.LoginUtilService;
|
|
|
+import com.rongwei.rwadmincommon.system.service.SysUserService;
|
|
|
+import com.rongwei.rwadmincommon.system.vo.JwtAuthenticationRequest;
|
|
|
+import com.rongwei.rwadmincommon.system.vo.SysUserVo;
|
|
|
+import com.rongwei.rwcommon.base.R;
|
|
|
+import com.rongwei.rwcommon.utils.Constants;
|
|
|
+import com.rongwei.rwcommon.utils.SecurityUtil;
|
|
|
+import com.rongwei.rwcommonentity.commonservers.domain.TenantDo;
|
|
|
+import com.rongwei.zhsw.code.dao.TenantDao;
|
|
|
+import com.rongwei.zhsw.code.fegin.LoginAuth;
|
|
|
+import com.rongwei.zhsw.code.service.LoginLogicService;
|
|
|
+import lombok.SneakyThrows;
|
|
|
+import org.apache.commons.lang.StringUtils;
|
|
|
+import org.slf4j.Logger;
|
|
|
+import org.slf4j.LoggerFactory;
|
|
|
+import org.springframework.beans.BeanUtils;
|
|
|
+import org.springframework.beans.factory.annotation.Autowired;
|
|
|
+import org.springframework.beans.factory.annotation.Value;
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
+import org.springframework.web.context.request.RequestContextHolder;
|
|
|
+import org.springframework.web.context.request.ServletRequestAttributes;
|
|
|
+
|
|
|
+import javax.servlet.http.HttpServletRequest;
|
|
|
+import java.util.*;
|
|
|
+import java.util.stream.Collectors;
|
|
|
+
|
|
|
+/**
|
|
|
+ * LoginLogicServiceImpl class
|
|
|
+ *
|
|
|
+ * @author XH
|
|
|
+ * @date 2021/12/13
|
|
|
+ */
|
|
|
+@Service
|
|
|
+public class LoginLogicServiceImpl implements LoginLogicService {
|
|
|
+ private final Logger log = LoggerFactory.getLogger(this.getClass().getName());
|
|
|
+ @Autowired
|
|
|
+ private LoginUtilService loginUtilService;
|
|
|
+ @Autowired
|
|
|
+ private RedisService redisService;
|
|
|
+ @Autowired
|
|
|
+ private SysUserService sysUserService;
|
|
|
+ @Autowired
|
|
|
+ private TenantDao tenantDao;
|
|
|
+ @Autowired
|
|
|
+ private LoginAuth loginAuth;
|
|
|
+
|
|
|
+ @Value("${login.checkPhoneNumErrorMsg:手机号码未注册!}")
|
|
|
+ private String checkPhoneNumErrorMsg;
|
|
|
+ @Value("${login.primarySchemaId:1}")
|
|
|
+ private String primarySchemaId;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 移动端登录标识
|
|
|
+ */
|
|
|
+ private static final String MOBILE_CLIENT_TYPE = "YD";
|
|
|
+ private static final String MOBILE_LOGING_DEFAULT_ERROR = "没有找到该手机号绑定的账号";
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 手机账号登录逻辑处理
|
|
|
+ *
|
|
|
+ * @param userLogin
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ @SneakyThrows
|
|
|
+ @Override
|
|
|
+ public R mobilePhoneLogin(UserLoginVo userLogin) {
|
|
|
+ // 登录验证码处理
|
|
|
+ loginUtilService.smsVerify(userLogin);
|
|
|
+ // 当前登录人的电话号码
|
|
|
+ String phoneNum = userLogin.getUsername();
|
|
|
+ if (StringUtils.isBlank(phoneNum)) {
|
|
|
+ log.error("登录手机号码为空");
|
|
|
+ throw new RuntimeException("请输入正确的手机号码");
|
|
|
+ }
|
|
|
+ // 从Redis 获取所有租户的用户信息
|
|
|
+ Map<String, List<SysUserDo>> allTenantUsers = (Map<String, List<SysUserDo>>) redisService.getRedisCatchObj("allTenantUsers");
|
|
|
+ if (allTenantUsers == null) {
|
|
|
+ log.error("无法获取租户和用户信息");
|
|
|
+ throw new RuntimeException("无法获取租户以及用户信息!请联系系统管理员");
|
|
|
+ }
|
|
|
+ // 获取需要展示的租户信息
|
|
|
+ TenantDo loginTenantDo = getTenantDo(userLogin, allTenantUsers, phoneNum);
|
|
|
+ // 切换至对应的Schema
|
|
|
+ ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
|
|
|
+ HttpServletRequest srequest = attributes.getRequest();
|
|
|
+ srequest.setAttribute(Constants.SAAS_LOGIN_TOKEN, loginTenantDo.getDskey());
|
|
|
+ // 从缓存中取出用户信息
|
|
|
+ SysUserDo loginUser = allTenantUsers.get(loginTenantDo.getId()).stream()
|
|
|
+ .filter(user -> phoneNum.equals(user.getMobile()))
|
|
|
+ .findFirst()
|
|
|
+ .orElse(null);
|
|
|
+ if (loginUser == null) {
|
|
|
+ log.error("无法获取登录的用户信息");
|
|
|
+ throw new RuntimeException("无法获取登录的用户信息");
|
|
|
+ }
|
|
|
+ SysUserVo sysUserVo = new SysUserVo();
|
|
|
+ BeanUtils.copyProperties(loginUser, sysUserVo);
|
|
|
+ // 设置租户信息
|
|
|
+ sysUserVo.setTenantDo(loginTenantDo);
|
|
|
+ // 生成token
|
|
|
+ JwtAuthenticationRequest jwtAuthenticationRequest = new JwtAuthenticationRequest(sysUserVo.getId(), sysUserVo.getAccount(), sysUserVo.getName());
|
|
|
+ jwtAuthenticationRequest.setExpire(-1);
|
|
|
+ Map<String, Object> tokenmap = loginAuth.getTokenInfo(jwtAuthenticationRequest);
|
|
|
+ String token = (String) tokenmap.get("token");
|
|
|
+ // 获取当前用户的角色 组织机构 和 权限
|
|
|
+ loginUtilService.setUserRoleAndOrg(sysUserVo);
|
|
|
+ // 菜单
|
|
|
+ Map<String, Object> map = new HashMap<>();
|
|
|
+ map.put("token", token);
|
|
|
+ map.put("userInfo", sysUserVo);
|
|
|
+ //redis缓存登录用户信息
|
|
|
+ redisService.setLoginUser(token, sysUserVo);
|
|
|
+ return R.ok(map);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 账号密码登录逻辑
|
|
|
+ * @param userLogin
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ @SneakyThrows
|
|
|
+ @Override
|
|
|
+ public R accountLogin(UserLoginVo userLogin) {
|
|
|
+ Map<String, List<SysUserDo>> allTenantUsers = (Map<String, List<SysUserDo>>) redisService.getRedisCatchObj("allTenantUsers");
|
|
|
+ // 是否为融公社管理员登录
|
|
|
+// if (userLogin.isCheckPrimaryLibrary()) {
|
|
|
+// // 校验当前账号是否属于 主库
|
|
|
+// // 获取主库中的用户信息
|
|
|
+// List<SysUserDo> sysUserDos = allTenantUsers == null ? new ArrayList<>() : allTenantUsers.getOrDefault(primarySchemaId, new ArrayList<>());
|
|
|
+// // 校验当前登录账号是否穿在
|
|
|
+// boolean hasUser = sysUserDos.stream().anyMatch(user -> userLogin.getUsername().equals(user.getAccount()));
|
|
|
+// // 不存在提示错误信息
|
|
|
+// if (!hasUser) {
|
|
|
+// log.error("当前登录账号:{} 在主库中不存在", userLogin.getUsername());
|
|
|
+// throw new RuntimeException("账号或密码错误");
|
|
|
+// }
|
|
|
+// if (!allTenantUsers.containsKey(primarySchemaId)) {
|
|
|
+// log.error("无法获取主库信息");
|
|
|
+// throw new RuntimeException("无法获取主库信息!请联系系统管理员");
|
|
|
+// }
|
|
|
+// // 获取租户信息
|
|
|
+// List<TenantDo> tenantDoList = tenantDao.getTenantDosById(Arrays.asList(primarySchemaId.split(",")));// (List<TenantDo>) redisService.getRedisCatchObj("allTenants");
|
|
|
+// if (tenantDoList.isEmpty()) {
|
|
|
+// log.error("无法通过id:{},获取到租户信息.", primarySchemaId);
|
|
|
+// throw new RuntimeException("无法获取租户信息,请联系管理员!");
|
|
|
+// }
|
|
|
+// ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
|
|
|
+// HttpServletRequest srequest = attributes.getRequest();
|
|
|
+// srequest.setAttribute(Constants.SAAS_LOGIN_TOKEN, tenantDoList.get(0).getDskey());
|
|
|
+// } else {
|
|
|
+ // 设置对应的Schema
|
|
|
+ loginUtilService.saasLoginToken(userLogin);
|
|
|
+ // }
|
|
|
+ // 校验用户名正确性
|
|
|
+ SysUserDo sysUser = new SysUserDo();
|
|
|
+ sysUser.setAccount(userLogin.getUsername());
|
|
|
+ SysUserDo sysUserDo = sysUserService.getOne(new QueryWrapper(sysUser));
|
|
|
+ if (sysUserDo == null || com.rongwei.rwcommon.utils.StringUtils.isEmpty(sysUserDo.getId())) {
|
|
|
+ // 防攻击,模糊提醒
|
|
|
+ throw new RuntimeException("用户名密码不正确");
|
|
|
+ }
|
|
|
+ if ("1".equals(sysUserDo.getEnabled())) {
|
|
|
+ throw new RuntimeException("此用户不可用,请联系管理员");
|
|
|
+ }
|
|
|
+ // 校验登录密码正确性
|
|
|
+ String secPas = SecurityUtil.getSaltMd5AndSha(userLogin.getPassword(), sysUserDo.getId());
|
|
|
+ if (!secPas.equals(sysUserDo.getPassword())) {
|
|
|
+ throw new RuntimeException("用户名密码不正确");
|
|
|
+ }
|
|
|
+ // token生成
|
|
|
+ JwtAuthenticationRequest jwtAuthenticationRequest = new JwtAuthenticationRequest(sysUserDo.getId(), sysUserDo.getAccount(), sysUserDo.getName());
|
|
|
+ if (userLogin.getClientType() != null && "YD".equals(userLogin.getClientType())) {
|
|
|
+ jwtAuthenticationRequest.setExpire(-1);
|
|
|
+ }
|
|
|
+ Map<String, Object> tokenmap = loginAuth.getTokenInfo(jwtAuthenticationRequest);
|
|
|
+ String token = (String) tokenmap.get("token");
|
|
|
+ if ("ServerAbnormal".equals(token)) {
|
|
|
+ throw new RuntimeException("认证服务异常");
|
|
|
+ }
|
|
|
+ // 组织返回给前端的用户信息
|
|
|
+ SysUserVo sysUserVo = new SysUserVo();
|
|
|
+ BeanUtils.copyProperties(sysUserDo, sysUserVo);
|
|
|
+ sysUserService.getUserRoleOrgPer(sysUserVo);
|
|
|
+ // 设置登录用户的租户信息
|
|
|
+ loginUtilService.setUserTenant(sysUserDo, sysUserVo);
|
|
|
+ // 菜单
|
|
|
+ Map<String, Object> map = new HashMap<>();
|
|
|
+ map.put("token", token);
|
|
|
+ map.put("userInfo", sysUserVo);
|
|
|
+ //redis缓存登录用户信息
|
|
|
+ redisService.setLoginUser(token, sysUserVo);
|
|
|
+ return R.ok(map);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取租户信息
|
|
|
+ *
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ private TenantDo getTenantDo(UserLoginVo userLogin, Map<String, List<SysUserDo>> allTenantUsers, String phoneNum) {
|
|
|
+ // 校验登录人的手机号在主库中是否存在
|
|
|
+ if (userLogin.isCheckPrimaryLibrary()) {
|
|
|
+ List<SysUserDo> primaryUsers = allTenantUsers.getOrDefault(primarySchemaId, new ArrayList<>());
|
|
|
+ boolean hasUser = primaryUsers.stream().anyMatch(user -> phoneNum.equals(user.getMobile()));
|
|
|
+ if (!hasUser) {
|
|
|
+ log.error("当前登录的手机号码在主库中不存在");
|
|
|
+ throw new RuntimeException(MOBILE_LOGING_DEFAULT_ERROR);
|
|
|
+ }
|
|
|
+ List<TenantDo> tenantDosById = tenantDao.getTenantDosById(Arrays.asList(primarySchemaId.split(",")));
|
|
|
+ if (tenantDosById.isEmpty()) {
|
|
|
+ log.error("无法通过id:{},获取到租户信息.", tenantDosById);
|
|
|
+ throw new RuntimeException("无法获取租户信息,请联系管理员!");
|
|
|
+ }
|
|
|
+ return tenantDosById.get(0);
|
|
|
+ }
|
|
|
+ List<SysUserDo> sysUserDos;
|
|
|
+ if (allTenantUsers == null) {
|
|
|
+ sysUserDos = new ArrayList<>();
|
|
|
+ } else {
|
|
|
+ // 从主库中获取手机号码相同的用户
|
|
|
+ if (userLogin.isCheckPrimaryLibrary()) {
|
|
|
+ sysUserDos = allTenantUsers.get(primarySchemaId)
|
|
|
+ .stream()
|
|
|
+ .filter(user -> primarySchemaId.equals(user.getTenantid()) && phoneNum.equals(user.getMobile()))
|
|
|
+ .collect(Collectors.toList());
|
|
|
+ } else {
|
|
|
+ // 从所有住户表中获取手机号码相同的用户
|
|
|
+ sysUserDos = allTenantUsers.values().stream()
|
|
|
+ .flatMap(Collection::stream)
|
|
|
+ .filter(user -> phoneNum.equals(user.getMobile()))
|
|
|
+ .collect(Collectors.toList());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (sysUserDos.isEmpty()) {
|
|
|
+ log.error("当前手机号码:{},未注册", phoneNum);
|
|
|
+ throw new RuntimeException(checkPhoneNumErrorMsg);
|
|
|
+ }
|
|
|
+ // 筛选出用户所属于的租户ID
|
|
|
+ List<String> tenantIdList = sysUserDos.stream().map(SysUserDo::getTenantid).distinct().collect(Collectors.toList());
|
|
|
+ // 获取租户信息
|
|
|
+ List<TenantDo> tenantDoList = tenantDao.getTenantDosById(tenantIdList);// (List<TenantDo>) redisService.getRedisCatchObj("allTenants");
|
|
|
+ if (tenantDoList == null) {
|
|
|
+ log.error("无法从缓存中获取租户信息");
|
|
|
+ throw new RuntimeException("无法从缓存中获取租户信息,请联系管理员!");
|
|
|
+ }
|
|
|
+// modify at [ 2022-07-06 15:33:08 ] by zxw: 许总说,去掉移动端引导
|
|
|
+ // YD端登录需要筛选出已激活的租户信息 PC端登录不受限制 并按照创建时间 由小到大排序
|
|
|
+// List<TenantDo> activateTenantList = tenantDoList.stream()
|
|
|
+// .filter(tenantInfo -> {
|
|
|
+// if (MOBILE_CLIENT_TYPE.equals(userLogin.getClientType())) {
|
|
|
+// return "2".equals(tenantInfo.getTenantstatus()) && tenantIdList.contains(tenantInfo.getId());
|
|
|
+// }
|
|
|
+// return true;
|
|
|
+// })
|
|
|
+// .sorted(Comparator.comparing(BaseDo::getCreatedate))
|
|
|
+// .collect(Collectors.toList());
|
|
|
+// if (MOBILE_CLIENT_TYPE.equals(userLogin.getClientType()) && activateTenantList.isEmpty()) {
|
|
|
+// log.error("当前用户:{}不存在已激活的租户信息 ", phoneNum);
|
|
|
+// throw new RuntimeException("请登录网页版,完成初始化配置");
|
|
|
+// }
|
|
|
+ return tenantDoList.get(0);
|
|
|
+ }
|
|
|
+}
|