ludc
2024-09-26 085df90e488067783759dcd63cdb5fb43a51ff1f
Source/plt-web/plt-web-parent/plt-web/src/main/java/com/vci/web/service/impl/LoginServiceImpl.java
@@ -1,33 +1,52 @@
package com.vci.web.service.impl;
import com.vci.corba.common.PLException;
import com.vci.corba.framework.data.DeptInfo;
import com.vci.corba.framework.data.LoginResult;
import com.vci.corba.framework.data.LoginState;
import com.vci.corba.framework.data.MachineInfo;
import com.vci.frameworkcore.ajaxTask.SmUserUnLockTask;
import com.vci.frameworkcore.ajaxTask.SmUserUnLockTaskManager;
import com.vci.frameworkcore.compatibility.ISmFunctionQueryService;
import com.vci.frameworkcore.compatibility.SmRoleQueryServiceI;
import com.vci.frameworkcore.compatibility.SmPwdStrategyQueryServiceI;
import com.vci.frameworkcore.compatibility.SmUserQueryServiceI;
import com.vci.frameworkcore.pagemodel.SmUserVO;
import com.vci.frameworkcore.enumpck.ResourceControlTypeEnum;
import com.vci.frameworkcore.lcstatuspck.FrameworkDataLCStatus;
import com.vci.pagemodel.SmFunctionVO;
import com.vci.pagemodel.SmPasswordStrategyVO;
import com.vci.pagemodel.SmUserVO;
import com.vci.frameworkcore.properties.VciSecurityManageProperties;
import com.vci.starter.web.annotation.bus.*;
import com.vci.starter.web.annotation.bus.VciLoginAfter;
import com.vci.starter.web.annotation.bus.VciLogoutBefore;
import com.vci.starter.web.annotation.bus.VciLogoutPlugin;
import com.vci.starter.web.exception.VciBaseException;
import com.vci.starter.web.interceptor.VciSessionForLoginI;
import com.vci.starter.web.pagemodel.RequestClientInfo;
import com.vci.starter.web.pagemodel.SessionInfo;
import com.vci.starter.web.util.ApplicationContextProvider;
import com.vci.starter.web.util.Md5;
import com.vci.starter.web.util.VciBaseUtil;
import com.vci.web.bo.LoginResultBO;
import com.vci.web.dto.LoginUserDTO;
import com.vci.starter.web.pagemodel.TokenVO;
import com.vci.starter.web.util.*;
import com.vci.bo.LoginResultBO;
import com.vci.constant.CacheNameConstant;
import com.vci.dto.LoginUserDTO;
import com.vci.web.properties.WebProperties;
import com.vci.web.redis.RedisService;
import com.vci.web.service.LoginServiceI;
import com.vci.web.util.BusAnnotationUtil;
import com.vci.web.util.Func;
import com.vci.web.util.PlatformClientUtil;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import javax.annotation.Resource;
import java.lang.reflect.Method;
import java.util.Map;
import java.text.MessageFormat;
import java.util.*;
import java.util.stream.Collectors;
import static com.vci.constant.FrameWorkBusLangCodeConstant.*;
/**
 * 登录的服务
@@ -45,38 +64,73 @@
    /**
     * 会话处理
     */
    @Autowired
    @Resource
    private VciSessionForLoginI sessionForLogin;
    /**
     * 解锁任务
     */
    @Autowired
    @Resource
    private SmUserUnLockTaskManager unLockTaskManager;
    /**
     * 权限管理的相关配置
     */
    @Autowired
    @Resource
    private VciSecurityManageProperties securityManageProperties;
    /**
     * 用户查询服务,可以兼容老平台
     */
    @Autowired()
    @Resource
    private SmUserQueryServiceI userQueryService;
    /**
     * 密码策略查询服务
     */
    @Resource
    private SmPwdStrategyQueryServiceI pwdStrategyQueryService;
    /**
     * 功能菜单的查询服务
     */
    @Resource
    private ISmFunctionQueryService functionQueryService;
    /**
     * 角色的查询服务,可以兼容老平台
     */
    @Autowired
    private SmRoleQueryServiceI roleQueryService;
    //@Resource
    //private SmRoleQueryServiceI roleQueryService;
    /**
     * 权限的查询服务,可以兼容老平台
     */
    @Autowired
    private ISmFunctionQueryService functionQueryService;
    //@Resource
    //private ISmFunctionQueryService functionQueryService;
    /**
     * redis服务
     */
    @Resource
    private RedisService redisService;
    /**
     * 客户端配置文件
     */
    @Resource
    private WebProperties webProperties;
    /**
     * 平台调用客户端
     */
    @Resource
    private PlatformClientUtil platformClientUtil;
    /**
     * 当前登录的用户总数key
     */
    private static final String CURRENT_LOGGED_USERS_KEY = "current_logged_users";
    /**
     * 执行登录
@@ -85,7 +139,7 @@
     * @throws VciBaseException 登录发生异常的时候出现了错误
     */
    @Override
    public LoginResultBO login(LoginUserDTO userDTO, RequestClientInfo clientInfo) throws VciBaseException {
    public LoginResultBO login(LoginUserDTO userDTO, RequestClientInfo clientInfo) throws PLException {
        return login(userDTO,clientInfo,true);
    }
@@ -97,201 +151,378 @@
     * @return 执行结果
     * @throws VciBaseException 参数错误,用户不能登录等会抛出异常
     */
    private LoginResultBO login(LoginUserDTO userDTO, RequestClientInfo clientInfo, boolean checkPassword) throws VciBaseException {
    private LoginResultBO login(LoginUserDTO userDTO, RequestClientInfo clientInfo, boolean checkPassword/*单点登录不需要校验密码*/) throws VciBaseException, PLException {
        LoginResultBO loginResult = new LoginResultBO();
        loginResult.setSuccess(false);
        //1.判断用户的基本信息
//        VciBaseUtil.alertNotNull(userDTO, "登录信息", userDTO.getUserId(), "用户账号");
//        if (checkPassword) {
//            VciBaseUtil.alertNotNull(userDTO.getPassword(), "登录密码");
//        }
        //登录之前调用插件
        BusAnnotationUtil.callForAnnotation(VciLoginPlugin.class,VciLoginBefore.class,userDTO,clientInfo);
//        String loginInfo = checkIsLogined(userDTO.getUserId());
//        if (!userDTO.isForceLogin() && securityManageProperties.isUserOneLogin()) {
//            //需要看看是否已经登录了
//            if (StringUtils.isNotBlank(loginInfo)) {
//                loginResult.setFailCode(USER_IS_LOGINED);
//                loginResult.setFailMsg(loginInfo);
//                return loginResult;
//            }
//        }
        //2.获取用户的对象.这里需要兼容老平台和老pdm,老编码和老平台是一个表
//        SmUserVO user = userQueryService.getUserByUserId(userDTO.getUserId().trim());
//        if (user == null || StringUtils.isEmpty(user.getOid())) {
//            loginResult.setFailCode(USER_NOT_FOUND);
//            loginResult.setFailMsgArray(new String[]{userDTO.getUserId()});
//            return loginResult;
//        }
        //1.判断用户的基本信息
        VciBaseUtil.alertNotNull(userDTO, "登录信息", userDTO.getUserId(), "用户账号");
        if (checkPassword) {
            VciBaseUtil.alertNotNull(userDTO.getPassword(), "登录密码");
        }
        //2、判断单设备登录,是否已经登录了
        String userIdTokenKey = CacheNameConstant.cacheKey(CacheNameConstant.USERID_TOKEN_KEY, userDTO.getUserId().trim());
        if(redisService.hasKey(userIdTokenKey) && !userDTO.isForceLogin() && securityManageProperties.isUserOneLogin()){
            loginResult.setFailCode(USER_IS_LOGINED);
            loginResult.setFailMsg("当前用户已经在其他地方登录!");
            return loginResult;
        }
        //说明已经登录了,那应该取消原来的登录
        if (redisService.hasKey(userIdTokenKey) && userDTO.isForceLogin() && securityManageProperties.isUserOneLogin()) {
            String tokenKey = redisService.getCacheObject(userIdTokenKey);
            redisService.deleteObject(tokenKey);
            redisService.deleteObject(userIdTokenKey);
            redisService.userLogout(CURRENT_LOGGED_USERS_KEY,userDTO.getUserId());
        }
        //3.获取用户的对象(对象中包含角色部门还有密码策略信息(当前用户没设置密码策略就是取的默认密码策略))
        SmUserVO user = getUserByUserId(userDTO.getUserId().trim());
        if (user == null || StringUtils.isBlank(user.getOid())) {
            loginResult.setFailCode(USER_NOT_FOUND);
            loginResult.setFailMsgArray(new String[]{userDTO.getUserId()});
            return loginResult;
        }
        //4、判断密码是否正确(平台的checkLogin方法好像有对密码进行比对的方法)
        /*if (checkPassword) {
            boolean passwordIsEqual = userQueryService.checkPasswordEqual(userDTO.getPassword(), user.getOid());
            if (!passwordIsEqual) {
                if (logger.isDebugEnabled()) {
                    logger.debug("{}密码不正确", user.getId());
                }
            }
        }*/
        //5、调用平台登录接口,进行登录
        MachineInfo machine = getMachieInfo(clientInfo);
        machine.country = clientInfo.getCountry();
        machine.language = clientInfo.getLanguage();
        machine.osUser = clientInfo.getOsUser();
        machine.machine = clientInfo.getMachine();
        String token = null;
        try {
            //前端传过来的密码是经过加密传输的,所以需要按照约定解密,再传给平台进行比对
            userDTO.setPassword(Func.decryptAes(userDTO.getPassword(),"daliantan0v0vcip"));
            LoginResult chkRes = platformClientUtil.getFrameworkService().checkLogin(userDTO.getUserId(),userDTO.getPassword(), machine);
            loginResult.setFailCode(getErrorCode(chkRes));
            //loginResult.setFailMsgArray(new String[]{userDTO.getUserId(), String.valueOf(chkRes.auxInfo)});
            loginResult.setFailMsgArray(new String[]{String.valueOf(chkRes.auxInfo)});
            //根据不同状态处理平台返回的信息
            if(chkRes.state.equals(LoginState.Error) || chkRes.state.equals(LoginState.Locked) || chkRes.state.equals(LoginState.Freeze)){
                return loginResult;
            }
            //关于密码策略相关的返回信息处理
            if(chkRes.state.equals(LoginState.InitialPW)){
                loginResult.setMustChangePassword(true);
                loginResult.setPasswordInfo("您的密码是管理员初始的密码,需要修改密码才能进行其它操作!");
                return loginResult;
            }else if(chkRes.state.equals(LoginState.PWExpired)){
                //需要立即修改密码
                loginResult.setMustChangePassword(true);
                loginResult.setPasswordInfo("您的密码已经过期,请进行修改!");
                return loginResult;
            }else if(chkRes.state.equals(LoginState.PWPolicyUpdated)){
                //策略修改,直接返回限制用户后续操作
                loginResult.setMustChangePassword(true);
                loginResult.setPasswordInfo("您的密码策略已经修改,需要修改密码才能进行其它操作!");
                return loginResult;
            }else if(chkRes.state.equals(LoginState.PWWillExpire)){
                loginResult.setPasswordInfo(String.format("您的密码有效期还有%s天,请注意修改!",chkRes.auxInfo));
            }
            token = chkRes.token;
        } catch (Exception e) {
            loginResult.setFailCode(SYSTEM_ERROR);
            loginResult.setFailMsgArray(new String[]{userDTO.getUserId()});
            return loginResult;
        }
        if(StringUtils.isBlank(token)){
            loginResult.setFailMsg(TOKEN_EMPTY);
            loginResult.setFailMsgArray(new String[]{userDTO.getUserId()});
            return loginResult;
        }
        //6、登录成功之后需要处理的逻辑
        user.setLastLoginTime(new Date());//最后登录时间
        user.setPwdWrongCount(0);//密码错误次数清0
        //处理用户登录成功的session
        SessionInfo sessionInfo = new SessionInfo();
        sessionInfo.setToken(token);
        //初始化平台的token
        sessionForLogin.initInvocationInfo(sessionInfo);
        //记录当前登录人数的总数
        redisService.userLogin(CURRENT_LOGGED_USERS_KEY,userDTO.getUserId());
        //拷贝用户到新的session会话中
        copyUser2SessionInfo(user, sessionInfo, userDTO.getLangCode());
        //拷贝请求信息到session会话中
        copyRequest2SessionInfo(clientInfo, sessionInfo);
        //查看了平台的登录方法其实是有处理部门角色等相关信息的但是不知道为什么无法获取到
        //部门信息处理
        sessionInfo.setDeptOid(user.getPkDepartment());
        sessionInfo.setDeptName(user.getPkDepartmentName());
        sessionInfo.setDeptNum(user.getPkDepartmentNum());
        //角色信息处理
        String roleOids = user.getPkPerson();
        String roleNames = user.getPkPersonName();
        HashMap<String, String> roleOidNameMap = new HashMap<>();
        if(Func.isNotBlank(roleOids) && Func.isNotBlank(roleOids)){
            String[] oids = roleOids.split(",");
            String[] names = roleNames.split(",");
            for (int i = 0; i < oids.length; i++) {
                roleOidNameMap.put(oids[i],names[i]);
            }
        }
        sessionInfo.setRolesName(roleOidNameMap);
        //查询所有的权限
        List<SmFunctionVO> functionVOList = functionQueryService.listFunctionByUserOid(user.getOid(), null, ResourceControlTypeEnum.BS);
        if (!CollectionUtils.isEmpty(functionVOList)) {
            List<String> functionOidList = functionVOList.stream().map(s -> s.getOid()).collect(Collectors.toList());
            sessionInfo.setFunctionOids(functionOidList);
        } else {
            sessionInfo.setFunctionOids(new ArrayList());
        }
        //添加到会话信息
        TokenVO tokenVO = saveSessionInfo(sessionInfo);
        loginResult.setTokenVO(tokenVO);
        loginResult.setSuccess(true);
        return loginResult;
    }
    /**
     * 登录_废弃方法,主要用来备份
     * @param userDTO 用户的数据传输对象
     * @param clientInfo 客户端的信息
     * @param checkPassword 是否校验密码
     * @return 执行结果
     * @throws VciBaseException 参数错误,用户不能登录等会抛出异常
     */
    private LoginResultBO login_old(LoginUserDTO userDTO, RequestClientInfo clientInfo, boolean checkPassword/*单点登录不需要校验密码*/) throws VciBaseException, PLException {
        LoginResultBO loginResult = new LoginResultBO();
        loginResult.setSuccess(false);
        //1.判断用户的基本信息
        VciBaseUtil.alertNotNull(userDTO, "登录信息", userDTO.getUserId(), "用户账号");
        if (checkPassword) {
            VciBaseUtil.alertNotNull(userDTO.getPassword(), "登录密码");
        }
        //2、判断单设备登录,是否已经登录了
        String userIdTokenKey = CacheNameConstant.cacheKey(CacheNameConstant.USERID_TOKEN_KEY, userDTO.getUserId().trim());
        if(redisService.hasKey(userIdTokenKey) && !userDTO.isForceLogin() && securityManageProperties.isUserOneLogin()){
            loginResult.setFailCode(USER_IS_LOGINED);
            loginResult.setFailMsg("当前用户已经在其他地方登录!");
            return loginResult;
        }
        //说明已经登录了,那应该取消原来的登录
        if (redisService.hasKey(userIdTokenKey) && userDTO.isForceLogin() && securityManageProperties.isUserOneLogin()) {
            String tokenKey = redisService.getCacheObject(userIdTokenKey);
            redisService.deleteObject(tokenKey);
            redisService.deleteObject(userIdTokenKey);
        }
        //3.获取用户的对象(对象中包含角色部门还有密码策略信息)
        SmUserVO user = getUserByUserId(userDTO.getUserId().trim());
        if (user == null || StringUtils.isBlank(user.getOid())) {
            loginResult.setFailCode(USER_NOT_FOUND);
            loginResult.setFailMsgArray(new String[]{userDTO.getUserId()});
            return loginResult;
        }
        //3、判断密码是否正确
        if (checkPassword) {
            boolean passwordIsEqual = userQueryService.checkPasswordEqual(userDTO.getPassword(), user.getOid());
            if (!passwordIsEqual) {
                if (logger.isDebugEnabled()) {
                    logger.debug("{}密码不正确", user.getId());
                }
            }
        }
        //4、调用平台登录接口,进行登录
        MachineInfo machine = getMachieInfo(clientInfo);
        machine.country = clientInfo.getCountry();
        machine.language = clientInfo.getLanguage();
        machine.osUser = clientInfo.getOsUser();
        machine.machine = clientInfo.getMachine();
        String token = null;
        try {
            LoginResult chkRes = platformClientUtil.getFrameworkService().checkLogin(userDTO.getUserId(),userDTO.getPassword(), machine);
            loginResult.setFailCode(getErrorCode(chkRes));
            loginResult.setFailMsgArray(new String[]{userDTO.getUserId(), String.valueOf(chkRes.auxInfo)});
            if(chkRes.state == LoginState.Error || chkRes.state == LoginState.Locked || chkRes.state == LoginState.Freeze){
                return loginResult;
            }
            token = chkRes.token;
        } catch (Exception e) {
            loginResult.setFailCode(SYSTEM_ERROR);
            loginResult.setFailMsgArray(new String[]{userDTO.getUserId()});
            return loginResult;
        }
        if(StringUtils.isBlank(token)){
            loginResult.setFailMsg(TOKEN_EMPTY);
            loginResult.setFailMsgArray(new String[]{userDTO.getUserId()});
            return loginResult;
        }
        //如果用户已经被停用和锁定,不能登录
        if (FrameworkDataLCStatus.DISABLED.getValue().equals(user.getLcStatus())) {
            loginResult.setFailCode(USER_IS_DISABLED);
            loginResult.setFailMsgArray(new String[]{userDTO.getUserId()});
            return loginResult;
        }
        if (userQueryService.checkUserLock(user, user.getPwdWrongCount())) {
            loginResult.setFailCode(USER_IS_LOCK);
            loginResult.setFailMsgArray(new String[]{userDTO.getUserId()});
            return loginResult;
        }
        //如果用户的失效日期已经超过了当前时间,不能登录
        //只有新平台的用户才判断失效
//        if (FrameworkDataLCStatus.DISABLED.getValue().equals(user.getLcStatus())) {
//            loginResult.setFailCode(USER_IS_DISABLED);
//            loginResult.setFailMsgArray(new String[]{userDTO.getUserId()});
//            return loginResult;
//        }
//        if (userQueryService.checkUserLock(user, user.getPwdWrongCount())) {
//            loginResult.setFailCode(USER_IS_LOCK);
//            loginResult.setFailMsgArray(new String[]{userDTO.getUserId()});
//            return loginResult;
//        }
//        if (user.getDisabledate() != null) {
//            //2021版本才有这个属性的值,当前这个没有这个值
//            Date disableDate = VciDateUtil.addOrSubDate(user.getDisabledate(), Calendar.DATE, 1);
//            if (disableDate != null && disableDate.getTime() < System.currentTimeMillis()) {
//                loginResult.setFailCode(USER_MORE_THAN_DISABLE_DATE);
//                loginResult.setFailMsgArray(new String[]{userDTO.getUserId()});
//                return loginResult;
//            }
//        }
//        if (user.getPwdWrongCount() == null) {
//            user.setPwdWrongCount(0);
//        }
//        SmPasswordStrategyVO passwordStrategyVO = userQueryService.getPasswordStrategyVOByUserOid(user.getOid());
//        if (checkPassword) {
//            boolean passwordIsEqual = userQueryService.checkPasswordEqual(userDTO.getPassword(), user.getOid());
//            //3.判断用户的密码是否正确
//            if (!passwordIsEqual) {
//                //前端需要先md5一次,然后后台再MD5一次,
//                if (logger.isDebugEnabled()) {
//                    logger.debug("{}密码不正确", user.getId());
//                }
//                if (passwordStrategyVO == null) {
//                    //可能数据问题没有设置密码策略
//                    passwordStrategyVO = new SmPasswordStrategyVO();
//                    passwordStrategyVO.setRetryTime(6);
//                    passwordStrategyVO.setLockTime(30);
//                }
//                if (passwordStrategyVO.getRetryTime() <= (user.getPwdWrongCount() + 1)) {
//                    user.setLockFlag(true);
//                    updateUserPwdWrongCount(user.getOid(), user.getPwdWrongCount() + 1);
//                    addUserToUnLock(userDTO.getUserId(), passwordStrategyVO.getLockTime());
//                    updateUserPwdWrongCount(user.getOid(), user.getPwdWrongCount() + 1);
//                    loginResult.setFailCode(USER_PWD_LOCK);
//                    loginResult.setFailMsgArray(new String[]{userDTO.getUserId(), passwordStrategyVO.getLockTime() + ""});
//                    return loginResult;
//                } else {
//                    //还没有到锁定的次数
//                    updateUserPwdWrongCount(user.getOid(), user.getPwdWrongCount() + 1);
//                    //5, 这是第一次错误,剩下的是 5- (0+1)
//                    loginResult.setFailCode(USER_PWD_NOT_EQUAL);
//                    loginResult.setFailMsgArray(new String[]{userDTO.getUserId(), (passwordStrategyVO.getRetryTime() - (user.getPwdWrongCount() + 1)) + ""});
//                    return loginResult;
//                }
//            }
//        }
        /*if (user.getDisabledate() != null) {
            //2021版本才有这个属性的值,当前这个没有这个值
            Date disableDate = VciDateUtil.addOrSubDate(user.getDisabledate(), Calendar.DATE, 1);
            if (disableDate != null && disableDate.getTime() < System.currentTimeMillis()) {
                loginResult.setFailCode(USER_MORE_THAN_DISABLE_DATE);
                loginResult.setFailMsgArray(new String[]{userDTO.getUserId()});
                return loginResult;
            }
        }*/
        //当前用户没有配置就查询默认的密码策略
        SmPasswordStrategyVO passwordStrategyVO = pwdStrategyQueryService.getPasswordStrategyVOByUserOid(user.getOid());
        if (checkPassword) {
            //前端需要先md5一次,然后后台再MD5一次,
            if (logger.isDebugEnabled()) {
                logger.debug("{}密码不正确", user.getId());
            }
            //只要数据没有问题就不存在密码策略为空的情况
            if (passwordStrategyVO == null) {
                //可能数据问题没有设置密码策略
                passwordStrategyVO = new SmPasswordStrategyVO();
                passwordStrategyVO.setRetryTime(6);
                passwordStrategyVO.setLockTime(30);
            }
            //判断密码错误次数是否达到上限
            if (passwordStrategyVO.getRetryTime() <= (user.getPwdWrongCount() + 1)) {
                user.setLockFlag(true);
                updateUserPwdWrongCount(user.getOid(), user.getPwdWrongCount() + 1);
                addUserToUnLock(userDTO.getUserId(), passwordStrategyVO.getLockTime());
                //updateUserPwdWrongCount(user.getOid(), user.getPwdWrongCount() + 1);
                loginResult.setFailCode(USER_PWD_LOCK);
                loginResult.setFailMsgArray(new String[]{userDTO.getUserId(), passwordStrategyVO.getLockTime() + ""});
                return loginResult;
            } else {
                //还没有到锁定的次数
                updateUserPwdWrongCount(user.getOid(), user.getPwdWrongCount() + 1);
                //5, 这是第一次错误,剩下的是 5- (0+1)
                loginResult.setFailCode(USER_PWD_NOT_EQUAL);
                loginResult.setFailMsgArray(new String[]{userDTO.getUserId(), (passwordStrategyVO.getRetryTime() - (user.getPwdWrongCount() + 1)) + ""});
                return loginResult;
            }
        }
        //检查是否该修改密码
        if (!clientInfo.isSso() && checkPassword) {
            //最后修改时间 + 失效时间,大于等于当前日期,则需要马上修改密码
            Date currentDay = null;
            try {
                currentDay = VciDateUtil.getNow(VciDateUtil.DateFormat);
            } catch (Throwable e) {
                if (logger.isErrorEnabled()) {
                    logger.error("获取当前日期", e);
                }
            }
            if (currentDay != null && passwordStrategyVO != null && passwordStrategyVO.getValidDay() != null) {
                Date inValidDay = null;
                if (user.getLastModifyPasswordTime() == null) {
                    //从来没有登录过
                    loginResult.setMustChangePassword(true);
                } else {
                    inValidDay = VciDateUtil.addOrSubDate(user.getLastModifyPasswordTime(), Calendar.DATE, passwordStrategyVO.getValidDay());
                    if (inValidDay.getTime() <= (currentDay).getTime()) {
                        loginResult.setMustChangePassword(true);
                    }
                }
                if (!loginResult.isMustChangePassword()) {
                    if (VciDateUtil.addOrSubDate(inValidDay, Calendar.DATE, -(passwordStrategyVO.getRemindDay())).getTime()
                            <= (currentDay).getTime()) {
                        //您的密码还有{0}天过期,请及时修改密码
                        long remainDay = VciDateUtil.getDaySub(inValidDay, currentDay);
                        loginResult.setPasswordInfo(MessageFormat.format(PASSWORD_REMAIN_DAY, new String[]{String.valueOf(remainDay)}));
                    }
                }
            }
        }
        //说明密码正确的
//        if (logger.isDebugEnabled()) {
//            logger.debug("{}的密码正确", user.getId());
//        }
//        user.setLastLoginTime(new Date());
//        user.setPwdWrongCount(0);
        SmUserVO user = new SmUserVO();
        user.setId("1");
        user.setName("1");
        user.setOid("1");
        user.setUserType("1");
        user.setUserTypeText("1");
        user.setSecretGrade(1);
        user.setSecretGradeText("1");
        user.setSex("1");
        user.setSexText("1");
        user.setPkPerson("1");
        user.setPkPersonName("1");
        user.setPkDepartment("1");
        user.setPkDepartmentName("1");
        user.setPkDuty("1");
        user.setPkDutyName("1");
        user.setEmail("1");
        user.setTel("1");
        user.setRtxNo("1");
        user.setIMNo("1");
        if (logger.isDebugEnabled()) {
            logger.debug("{}的密码正确", user.getId());
        }
        user.setLastLoginTime(new Date());
        user.setPwdWrongCount(0);
        SessionInfo sessionInfo = new SessionInfo();
        sessionInfo.setToken(token);
        //初始化平台的token
        sessionForLogin.initInvocationInfo(sessionInfo);
        //拷贝用户的新到session会话中
        copyUser2SessionInfo(user, sessionInfo, userDTO.getLangCode());
        //拷贝请求信息到session会话中
        copyRequest2SessionInfo(clientInfo, sessionInfo);
        //查询所有的角色
//        List<SmRoleVO> roleVOList = roleQueryService.listRoleByUserOid(user.getOid(), null);
//        if (!CollectionUtils.isEmpty(roleVOList)) {
//            Map<String, String> roleOidNameMap = roleVOList.stream().collect(Collectors.toMap(s -> s.getOid(), t -> t.getName()));
//            sessionInfo.setRolesName(roleOidNameMap);
//        } else {
//            sessionInfo.setRolesName(new HashMap());
//        }
        //查询所有的权限
//        List<SmFunctionVO> functionVOList = functionQueryService.listFunctionByUserOid(user.getOid(), null, ResourceControlTypeEnum.BS);
//        if (!CollectionUtils.isEmpty(functionVOList)) {
//            List<String> functionOidList = functionVOList.stream().map(s -> s.getOid()).collect(Collectors.toList());
//            sessionInfo.setFunctionOids(functionOidList);
//        } else {
//            sessionInfo.setFunctionOids(new ArrayList());
//        }
        loginResult.setSuccess(true);
        //检查是否该修改密码
//        if (!clientInfo.isSso() && checkPassword) {
//            //最后修改时间+ 失效时间,大于等于当前日期,则需要马上修改密码
//            Date currentDay = null;
//            try {
//                currentDay = VciDateUtil.getNow(VciDateUtil.DateFormat);
//            } catch (Throwable e) {
//                if (logger.isErrorEnabled()) {
//                    logger.error("获取当前日期", e);
//                }
//            }
//            if (currentDay != null && passwordStrategyVO != null && passwordStrategyVO.getValidDay() != null) {
//                Date inValidDay = null;
//                if (user.getLastModifyPasswordTime() == null) {
//                    //重来没有登录过
//                    loginResult.setMustChangePassword(true);
//                } else {
//                    inValidDay = VciDateUtil.addOrSubDate(user.getLastModifyPasswordTime(), Calendar.DATE, passwordStrategyVO.getValidDay());
//                    if (inValidDay.getTime() <= (currentDay).getTime()) {
//                        loginResult.setMustChangePassword(true);
//                    }
//                }
//                if (!loginResult.isMustChangePassword()) {
//                    if (VciDateUtil.addOrSubDate(inValidDay, Calendar.DATE, -(passwordStrategyVO.getRemindDay())).getTime()
//                            <= (currentDay).getTime()) {
//                        //您的密码还有{0}天过期,请及时修改密码
//                        long remainDay = VciDateUtil.getDaySub(inValidDay, currentDay);
//                        loginResult.setPasswordInfo(MessageFormat.format(PASSWORD_REMAIN_DAY, new String[]{String.valueOf(remainDay)}));
//                    }
//                }
//            }
//        }
        //获取人员所属的部门信息
        try {
            DeptInfo deptInfo = platformClientUtil.getFrameworkService().fetchDeptByUserId(user.getOid());
            sessionInfo.setDeptOid(deptInfo.id);
            sessionInfo.setDeptName(deptInfo.name);
            sessionInfo.setDeptNum(deptInfo.num);
        } catch (PLException e) {
            throw new VciBaseException("获取用户所属部门失败:"+e.getMessage());
        }
        //原本想使用jwt来生成token,但是有以下问题
        //1.jwt不能处理注销的问题
        //2.jwt生成的token太长了
        //3.因为本平台不是互联网系统,只需要解决分布式用户信息的获取和权限的校验即可。
        //4.平台引用了redis和数据库来存储会话的信息,只需要保证根据token能获取到会话信息即可
        //5.在服务启动的时候,将会话信息清除,在注销的时候将会话信息清除
        //uuid在高并发的情况下会重复,但是传统软件并发很小,所以出现的重复的概率很小
        sessionInfo.setToken(Md5.md5(VciBaseUtil.getPk() + "_" + user.getId()));
        loginResult.setSessionInfo(sessionInfo);
//        updateUserForLoginSuccess(user.getOid());
//        if (StringUtils.isNotBlank(loginInfo) && userDTO.isForceLogin() && securityManageProperties.isUserOneLogin()) {
//            //说明已经登录了,那应该取消原来的登录
//            popUser(userDTO.getUserId());
//        }
        /** //查询所有的角色
         List<SmRoleVO> roleVOList = roleQueryService.listRoleByUserOid(user.getOid(), null);
         if (!CollectionUtils.isEmpty(roleVOList)) {
         Map<String, String> roleOidNameMap = roleVOList.stream().collect(Collectors.toMap(s -> s.getOid(), t -> t.getName()));
         sessionInfo.setRolesName(roleOidNameMap);
         } else {
         sessionInfo.setRolesName(new HashMap());
         }
         //查询所有的权限
         List<SmFunctionVO> functionVOList = functionQueryService.listFunctionByUserOid(user.getOid(), null, ResourceControlTypeEnum.BS);
         if (!CollectionUtils.isEmpty(functionVOList)) {
         List<String> functionOidList = functionVOList.stream().map(s -> s.getOid()).collect(Collectors.toList());
         sessionInfo.setFunctionOids(functionOidList);
         } else {
         sessionInfo.setFunctionOids(new ArrayList());
         }*/
        //添加到会话信息
//        saveSessionInfo(sessionInfo);
        TokenVO tokenVO = saveSessionInfo(sessionInfo);
        loginResult.setTokenVO(tokenVO);
        //登录后执行
//        BusAnnotationUtil.callForAnnotation(VciLoginPlugin.class,VciLoginAfter.class,userDTO,clientInfo,loginResult);
        loginResult.setSuccess(true);
        return loginResult;
    }
    private MachineInfo getMachieInfo(RequestClientInfo clientInfo) {
        MachineInfo machine = new MachineInfo();
        machine.country = clientInfo.getCountry();
        machine.language = clientInfo.getLanguage();
        machine.osUser = clientInfo.getOsUser();
        machine.machine = clientInfo.getMachine();
        return machine;
    }
    /**
     * 获取用户信息
     * @param userId userId
     * @Return com.vci.frameworkcore.pagemodel.SmUserVO
     */
    private SmUserVO getUserByUserId(String userId) {
        return userQueryService.getUserByUserId(userId);
    }
    /**
     * 单点登录
@@ -302,7 +533,7 @@
     * @throws VciBaseException 登录失败的时候抛出异常
     */
    @Override
    public LoginResultBO singleLogin(LoginUserDTO userDTO, RequestClientInfo clientInfo) throws VciBaseException {
    public LoginResultBO singleLogin(LoginUserDTO userDTO, RequestClientInfo clientInfo) throws PLException {
        return login(userDTO,clientInfo,false);
    }
@@ -335,6 +566,8 @@
                }
            });
        }
        //清除存当前登录的用户(总数-1)
        redisService.userLogout(CURRENT_LOGGED_USERS_KEY,WebThreadLocalUtil.getCurrentUserSessionInfoInThread().getUserId());
        sessionForLogin.logout(userToken);
        if(!CollectionUtils.isEmpty(logoutpluginBeanMap)){
            logoutpluginBeanMap.forEach((k,v) -> {
@@ -358,37 +591,15 @@
    }
    /**
     * 校验是否登录
     * @param userId 用户名
     * @return 已经登录时,
     */
    private String checkIsLogined(String userId) {
        if(sessionForLogin == null){
            throw new VciBaseException("没有配置会话存储的服务");
        }
        return sessionForLogin.checkIsLogined(userId);
    }
    /**
     * 把以前的登录信息移除
     * @param userId 用户名
     */
    private void popUser(String userId){
        if(sessionForLogin == null){
            throw new VciBaseException("没有配置会话存储的服务");
        }
        sessionForLogin.popUser(userId);
    }
    /**
     * 保存会话信息
     * @param sessionInfo 会话信息
     */
    private void saveSessionInfo(SessionInfo sessionInfo){
    private TokenVO saveSessionInfo(SessionInfo sessionInfo){
        if(sessionForLogin == null){
            throw new VciBaseException("没有配置会话存储的服务");
        }
        sessionForLogin.saveSessionInfo(sessionInfo);
        WebThreadLocalUtil.setCurrentUserSessionInfoInThread(sessionInfo);
        return sessionForLogin.createToken(sessionInfo);
    }
    /**
@@ -438,10 +649,7 @@
        sessionInfo.setRtxNo(user.getRtxNo());
        sessionInfo.setIMId(user.getIMNo());
        sessionInfo.setPortalId(user.getId());
//        sessionInfo.setWorkNo(user.getWorkNo());
//        sessionInfo.setWorkTypeOid(user.getPkWorkType());
//        sessionInfo.setWorkTypeName(user.getPkWorkTypeText());
        sessionInfo.setLastLoginTime(user.getLastLoginTime()!=null?user.getLastLoginTime().getTime(): VciDateUtil.getNowTime());
    }
    /**
@@ -475,4 +683,42 @@
    private void updateUserForLoginSuccess(String userOid){
        userQueryService.updateUserLoginTime(userOid);
    }
    /**
     * 获取登录错误码
     * @param chkRes 平台登录校验结果
     * @Return java.lang.String
     */
    public String getErrorCode(LoginResult chkRes){
        String message = "";
        switch(chkRes.state.value())
        {
            case 0:
                return UNKNOWN;
            case 1:
                return LOGIN_SUCCESS;
            case 10:
                return USER_NOT_FOUND;
            case 11:
                return USER_PWD_NOT_EQUAL;
            case 12:
                return USER_IS_DISABLED;
            case 13:
                return USER_IS_LOCK;
            case 14:
                return PASSWORD_INIT;
            case 15:
                return PASSWORD_REMAIN_DAY;
            case 16:
                return PASSWORD_EXPIRE;
            case 17:
                return PASSWORD_POLICY_UPDATED;
            case 20:
                return SYSTEM_ERROR;
            default:
                message = SYSTEM_ERROR;
                break;
        }
        return message;
    }
}