Browse Source

租户登录

huangpeng 5 months ago
parent
commit
cfab585c41

+ 1 - 5
zhsw-common/pom.xml

@@ -12,11 +12,7 @@
     <artifactId>zhsw-common</artifactId>
 
     <dependencies>
-        <dependency>
-            <groupId>com.rongwei</groupId>
-            <artifactId>py-business-entity</artifactId>
-            <version>1.0-SNAPSHOT</version>
-        </dependency>
+
         <dependency>
             <groupId>com.baomidou</groupId>
             <artifactId>mybatis-plus-generator</artifactId>

+ 46 - 0
zhsw-server/src/main/java/com/rongwei/zhsw/code/controller/LoginLogicController.java

@@ -0,0 +1,46 @@
+package com.rongwei.zhsw.code.controller;
+
+
+import com.rongwei.rwadmincommon.system.domain.UserLoginVo;
+import com.rongwei.rwcommon.base.R;
+import com.rongwei.rwcommon.utils.SecurityUtil;
+import com.rongwei.zhsw.code.service.LoginLogicService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * LoginLogicController class
+ *
+ * @author XH
+ * @date 2021/11/26
+ */
+@RestController
+@RequestMapping("/login")
+public class LoginLogicController {
+    private final Logger log = LoggerFactory.getLogger(this.getClass().getName());
+
+    @Autowired
+    private LoginLogicService loginLogicService;
+
+
+    /**
+     * Core+ 通过账号密码登录和校验方法
+     *
+     * @param userLogin
+     * @return
+     */
+    @PostMapping("/account")
+    private R accountLogin(@RequestBody UserLoginVo userLogin) {
+        return loginLogicService.accountLogin(userLogin);
+    }
+
+    public static void main(String[] args) {
+        String secPas = SecurityUtil.getSaltMd5AndSha("000000", "559208316af045358aca22a86622d477");
+        System.out.println(secPas);
+    }
+}

+ 58 - 0
zhsw-server/src/main/java/com/rongwei/zhsw/code/dao/TenantDao.java

@@ -0,0 +1,58 @@
+package com.rongwei.zhsw.code.dao;
+
+import com.rongwei.rwadmincommon.system.domain.SysUserDo;
+import com.rongwei.rwcommon.base.BaseDao;
+import com.rongwei.rwcommonentity.commonservers.domain.TenantDo;
+import org.apache.ibatis.annotations.Param;
+import org.apache.ibatis.annotations.Select;
+import org.apache.ibatis.annotations.Update;
+import org.springframework.stereotype.Repository;
+
+import java.util.List;
+
+@Repository
+public interface TenantDao extends BaseDao<TenantDo> {
+
+    @Select("select * from zhsw_dev.sys_tenant where DELETED='0' and id = #{id} ")
+    TenantDo getById(@Param("id") String id);
+
+    @Select("select * from ${schema}.sys_user where DELETED='0'")
+    List<SysUserDo> userListBySchema(@Param("schema") String schema);
+
+    @Select("CREATE DATABASE IF NOT EXISTS ${dataBaseName} \n" +
+            "DEFAULT CHARACTER SET utf8mb4 \n" +
+            "DEFAULT COLLATE utf8mb4_general_ci")
+    void createTenantDataBase(@Param("dataBaseName") String dataBaseName);
+
+
+    /**
+     * 更新超级管理员的账号信息
+     * @param schema
+     * @param tenantid
+     */
+    @Update("update ${schema}.sys_user set TENANTID = #{tenantid},ACCOUNT = CONCAT('${schema}','admin') where ID ='8672bf72ab274bec83052868ae336b38' ")
+    void updateUserTenant(@Param("schema") String schema,@Param("tenantid") String tenantid);
+
+    /**
+     * 更新管理员的账号信息
+     * @param schema
+     * @param tenantid
+     * @param mobile
+     * @param name
+     */
+    @Update("update ${schema}.sys_user set TENANTID = #{tenantid},ACCOUNT = #{mobile},NAME = #{name},MOBILE = #{mobile} where ID = '3f9d36b25773416eb7abf65823845bd6'")
+    void updateUserInfo(@Param("schema") String schema,@Param("tenantid") String tenantid,@Param("mobile") String mobile,@Param("name") String name);
+
+    @Select("select database()")
+    String getThisDataBaseName();
+
+    @Select("SELECT SCHEMA_NAME FROM information_schema.SCHEMATA")
+    List<String> allSchemaName();
+    @Select("select TENANTCODE from zhsw_dev.sys_tenant where UNIFIEDSOCIALCREDITCODE = #{socialCreditUniformCode} ")
+    String getTenantCodeBySocialCreditUniformCode(String socialCreditUniformCode);
+
+    @Select("select UNIFIEDSOCIALCREDITCODE from zhsw_dev.sys_tenant where id = #{id} ")
+    String getSocialCreditUniformCodeByTenantCode(@Param("id") String id);
+
+    List<TenantDo> getTenantDosById(@Param("idList") List<String> ids);
+}

+ 16 - 0
zhsw-server/src/main/java/com/rongwei/zhsw/code/fegin/LoginAuth.java

@@ -0,0 +1,16 @@
+package com.rongwei.zhsw.code.fegin;
+
+import com.rongwei.rwadmincommon.system.vo.JwtAuthenticationRequest;
+import org.springframework.cloud.openfeign.FeignClient;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+
+import java.util.Map;
+
+@FeignClient(value = "rw-auth-server",fallback = LoginAuthImpl.class)
+public interface LoginAuth {
+
+    @PostMapping(value = "/jwt/token")
+    Map<String,Object> getTokenInfo(@RequestBody JwtAuthenticationRequest authenticationRequest);
+
+}

+ 17 - 0
zhsw-server/src/main/java/com/rongwei/zhsw/code/fegin/LoginAuthImpl.java

@@ -0,0 +1,17 @@
+package com.rongwei.zhsw.code.fegin;
+
+import com.rongwei.rwadmincommon.system.vo.JwtAuthenticationRequest;
+import org.springframework.stereotype.Component;
+
+import java.util.HashMap;
+import java.util.Map;
+
+@Component
+public class LoginAuthImpl implements LoginAuth{
+    @Override
+    public Map<String,Object> getTokenInfo(JwtAuthenticationRequest authenticationRequest) {
+        Map<String,Object> map = new HashMap<>();
+        map.put("msg","ServerAbnormal");
+        return map;
+    }
+}

+ 25 - 0
zhsw-server/src/main/java/com/rongwei/zhsw/code/fegin/TenantFeginService.java

@@ -0,0 +1,25 @@
+package com.rongwei.zhsw.code.fegin;
+
+import com.rongwei.rwcommon.base.R;
+import com.rongwei.rwcommonentity.commonservers.domain.TenantDo;
+import org.springframework.cloud.openfeign.FeignClient;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+
+import java.util.Map;
+
+@FeignClient(value = "rw-tenant",fallback = TenantFeginServiceImpl.class)
+public interface TenantFeginService {
+
+    @PostMapping(value = "/tenant/tenant/addTenantAccount")
+    R addTenantAccount(@RequestBody Map<String, Object> map);
+
+    @PostMapping(value = "/tenant/tenant/saveAndCreateDataSource")
+    R saveAndCreateDataSource(@RequestBody Map<String, Object> map);
+
+    @PostMapping(value = "/tenant/tenant/updateTenant")
+    R updateTenant(@RequestBody Map<String,TenantDo> tenantDoMap);
+
+    @PostMapping(value = "/tenant/tenant/refreshUser")
+    R refreshUser();
+}

+ 38 - 0
zhsw-server/src/main/java/com/rongwei/zhsw/code/fegin/TenantFeginServiceImpl.java

@@ -0,0 +1,38 @@
+package com.rongwei.zhsw.code.fegin;
+
+import com.codingapi.txlcn.tc.support.DTXUserControls;
+import com.codingapi.txlcn.tracing.TracingContext;
+import com.rongwei.rwcommon.base.R;
+import com.rongwei.rwcommonentity.commonservers.domain.TenantDo;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Component;
+
+import java.util.Map;
+
+@Slf4j
+@Component
+public class TenantFeginServiceImpl implements TenantFeginService {
+
+    @Override
+    public R addTenantAccount(Map<String, Object> map) {
+        DTXUserControls.rollbackGroup(TracingContext.tracing().groupId());
+        return R.error("Tenant服务addTenantAccount请求调用失败");
+    }
+
+    @Override
+    public R updateTenant(Map<String,TenantDo> tenantDoMap) {
+        DTXUserControls.rollbackGroup(TracingContext.tracing().groupId());
+        return R.error("Tenant服务updateTenant请求调用失败");
+    }
+
+    @Override
+    public R refreshUser() {
+        return R.error("Tenant服务refreshUser请求调用失败");
+    }
+
+    @Override
+    public R saveAndCreateDataSource(Map<String, Object> map) {
+        DTXUserControls.rollbackGroup(TracingContext.tracing().groupId());
+        return R.error("Tenant服务updateTenant请求调用失败");
+    }
+}

+ 26 - 0
zhsw-server/src/main/java/com/rongwei/zhsw/code/service/LoginLogicService.java

@@ -0,0 +1,26 @@
+package com.rongwei.zhsw.code.service;
+
+import com.rongwei.rwadmincommon.system.domain.UserLoginVo;
+import com.rongwei.rwcommon.base.R;
+
+/**
+ * LoginLogicService class
+ *
+ * @author XH
+ * @date 2021/12/13
+ */
+public interface LoginLogicService {
+    /**
+     * 手机号码登录
+     * @param userLogin
+     * @return
+     */
+    R mobilePhoneLogin(UserLoginVo userLogin);
+
+    /**
+     * 账号密码登录
+     * @param userLogin
+     * @return
+     */
+    R accountLogin(UserLoginVo userLogin);
+}

+ 270 - 0
zhsw-server/src/main/java/com/rongwei/zhsw/code/service/impl/LoginLogicServiceImpl.java

@@ -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);
+    }
+}

+ 1 - 1
zhsw-server/src/main/resources/bootstrap-dev.yml

@@ -6,7 +6,7 @@ spring:
         server-addr: 127.0.0.1:8848
         namespace: cd047569-9470-4dfb-8663-b113d01cd30f
         ext-config[0]:
-          data-id: common-config-js.yaml
+          data-id: common-config.yaml
       discovery:
         server-addr: 127.0.0.1:8848
         namespace: cd047569-9470-4dfb-8663-b113d01cd30f