package com.vci.client.logon.base; import java.text.MessageFormat; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.Locale; import com.vci.client.ClientSession; import com.vci.client.common.objects.ClientInfo; import com.vci.client.common.objects.UserEntityObject; import com.vci.client.common.objects.UserLogonObject; import com.vci.client.common.objects.UserObject; import com.vci.client.framework.appConfig.object.AppConfigDetailObject; import com.vci.client.framework.delegate.AppConfigDetailClientDelegate; import com.vci.client.framework.delegate.RightManagementClientDelegate; import com.vci.client.framework.systemConfig.object.CombinationObject; import com.vci.client.framework.systemConfig.object.CombinationValueObject; import com.vci.client.framework.systemConfig.object.PasswordStrategyObject; import com.vci.client.framework.util.RightControlUtil; import com.vci.client.ui.exception.VCIException; import com.vci.client.ui.locale.LocaleDisplay; import com.vci.corba.common.VCIError; import com.vci.corba.framework.data.DataSourceInfo; import com.vci.mw.ClientContextVariable; /** * 通用的用户登录处理逻辑 * *

Title:

*

Description:

*

Copyright: Copyright (c) 2016

*

Company: VCI

* @author xiongchao * @time 2017-1-12 * @version 1.0 */ public class LogonHandler { private RightManagementClientDelegate rmcd = new RightManagementClientDelegate(); private int defaultWrongNum = 5; private int defaultLogonTime = 30; private int dafaultOverdueDay = 30; private int dafaultRemideDay = 5; private String getI18n(String key){ return LocaleDisplay.getI18nString(key, "RMIPFramework", Locale.getDefault()); } private String getThisI18n(String key){ return getI18n(getClass().getSimpleName() + "." + key); } public LogonResult checkLogin(String userName, String passWord, String clientIP) throws VCIError, VCIException { return checkLogin(userName, passWord, clientIP, true); } public LogonResult checkLogin(String userName, String passWord, String clientIP, boolean pwdStagVerify) throws VCIError, VCIException { return checkLogin(userName, passWord, clientIP, pwdStagVerify, false); } public LogonResult checkLoginForBS(String userName, String passWord, String clientIP, boolean pwdStagVerify) throws VCIError, VCIException { return checkLogin(userName, passWord, clientIP, pwdStagVerify, true); } protected LogonResult checkLogin(String userName, String passWord, String clientIP, boolean pwdStagVerify, boolean forBS) throws VCIError, VCIException { rmcd = new RightManagementClientDelegate(getUserEntityObject(userName, clientIP)); LogonResult res = new LogonResult(); // 已存在用户 UserObject existUserObj = getUserObjToLock(userName); if("".equals(existUserObj.getId())){ // 用户名不存在 return new LogonResult(false, getThisI18n("userNameNotExists")); } // 已存在用户的登录信息 UserLogonObject userLogonObj = getUserLogonObj(existUserObj.getId()); PasswordStrategyObject pwdStgObj = null; if(pwdStagVerify){ // 用户的密码策略默认密码策略 if (!(RightControlUtil.isAdminOrDeveloperOrRoot(userName))) { pwdStgObj = rmcd.fetchPasswordStrategyByUserId(existUserObj.getId()); } } // 没有密码策略的场景 if(pwdStgObj == null || "".equals(pwdStgObj.getId())){ // 没有密码策略时的登录认证逻辑 UserObject userObj = checkLoginToSystem(userName, passWord, clientIP); if(userObj == null){ // 用户名或密码错误 return new LogonResult(false, getThisI18n("userNameOrPwdWrong")); } // 登录成功 res.setSuccess(true); res.setMessage(""); res.setLogonedUserObject(userObj); // add by xchao 2017.12.13 begin // 在登录结果中加入当前登录用户所代表的VCIInvationInfo对象 res.setInvocationInfo(rmcd.getLogonedUserInvocationInfo(userObj, getClientInfo(clientIP), forBS)); // add by xchao 2017.12.13 end } else { // 有密码策略的登录校验场景 res = checkLogiForNoPwdStage(userName, passWord, clientIP, existUserObj, userLogonObj, pwdStgObj, forBS); } LogonResult ipChkRes = checkUserIPSecetIsOk(userName); if(ipChkRes != null){ res = ipChkRes; } return res; } private LogonResult checkUserIPSecetIsOk(String userName) throws VCIException{ AppConfigDetailClientDelegate delegate = new AppConfigDetailClientDelegate(rmcd.getUserEntityObject()); AppConfigDetailObject ipConfigDetail = delegate.getAppConfigDetailByKey("ipSecuritySwitch"); AppConfigDetailObject userConfigDetail = delegate.getAppConfigDetailByKey("userSecuritySwith"); String machineSwitch = ipConfigDetail.getValue();//value值为on时代表机器密级开启,值为其他或者不配置时代表不开启。 String userSwitch = userConfigDetail.getValue();//value值为on时代表用户密级开启,值为其他或者不配置时代表不开启。 if(machineSwitch.equals("on") && userSwitch.equals("on")){ String machineValue = ClientContextVariable.getVariablebyKey(userName, "CURRENTMACHINE.SECRET");//机器密级 String userValue = ClientContextVariable.getUserInvocation(userName).secretGrade;//用户密级 if(Integer.parseInt(userValue) < Integer.parseInt(machineValue)){ // 用户密级与机器密级不匹配,登录失败! return new LogonResult(false, getThisI18n("userSecretNotMatchMachineSecret")); } } return null; } /** * * @param userName * @param passWord * @param existUserObj * @param userLogonObj * @param pwdStgObj * @return * @throws VCIException */ private LogonResult checkLogiForNoPwdStage( String userName, String passWord, String clientIP, UserObject existUserObj, UserLogonObject userLogonObj, PasswordStrategyObject pwdStgObj, boolean forBS) throws VCIError, VCIException { LogonResult res = new LogonResult(); // 有密码策略的场景 defaultWrongNum = pwdStgObj.getRetryTime(); // 获取密码策略规定的错误登录次数 defaultLogonTime = pwdStgObj.getLockTime(); // 获取密码策略规定的锁定时间 dafaultOverdueDay = pwdStgObj.getOverdueDay(); // 获取密码规则的过期天数 dafaultRemideDay = pwdStgObj.getRemideDay(); // 获取密码策略规定的密码快过期提醒天数(提前xx天开始提醒该修改密码) // 取出最后一次的登录信息 // 如果在 锁定时间范围内密码错误次数已经超出密码策略限制 // 则给出用户已锁定的提示 int wrongNum = userLogonObj.getPlWrongNum(); long lastLogonTime = userLogonObj.getPlLogonTime() + 1; long systemTime = 0; systemTime = rmcd.getSystemTime(); int timeGap = compare_time(lastLogonTime, systemTime, true); if(wrongNum > 0 && wrongNum >= defaultWrongNum && timeGap < defaultLogonTime) { // 在锁定时间范围内,密码错误次数已经超出了密码策略所允许的最大值, // 此时直接给出 用户已被锁定的提示 int remainTime = defaultLogonTime - timeGap; // "该用户已被锁定,请等" + remainTime + "分钟之后再尝试登录,或找管理员解锁!") return new LogonResult(false, MessageFormat.format(getThisI18n("userIsLockedPleaseWaitSomeTimeToTry"), remainTime)); } // 按正常的用户认证逻辑进行认证校验 // 真实的检查用户名、密码是否正确匹配 UserObject userObj = checkLoginToSystem(userName, passWord, clientIP); if(userObj == null || (userObj != null && "".equals(userObj.getId()))){ // 记录登录错误信息 updateLogonInfo(existUserObj.getId(), false); // 用户名或密码错误 res = new LogonResult(false, getThisI18n("userNameOrPwdWrong")); // 重新查出用户的登录记录信息 userLogonObj = getUserLogonObj(existUserObj.getId()); // 计算错误次数是否超出密码策略的限制 if (userLogonObj != null && !RightControlUtil.isAdmin(userName) && !RightControlUtil.isDeveloper(userName)) { wrongNum = userLogonObj.getPlWrongNum(); lastLogonTime = userLogonObj.getPlLogonTime() + 1; systemTime = rmcd.getSystemTime(); timeGap = compare_time(lastLogonTime, systemTime, true); if(wrongNum>=1 && wrongNum< defaultWrongNum){ res.setMessage(res.getMessage()+"还有"+(defaultWrongNum-wrongNum)+"次机会将被锁定"); } if (wrongNum >= defaultWrongNum && timeGap < defaultLogonTime) { // 用户登陆失败时候记录相关日志信息 if (!RightControlUtil.isAdminOrDeveloperOrRoot(userName)) { // 登陆错误次数过多,登入系统失败!用户已被锁定! rmcd.savelogFail(getThisI18n("userLoginWrongTooMuch")); } int remainTime = defaultLogonTime - timeGap; // 记录锁定用户的日志记录 rmcd.blocklog(existUserObj.getId()); // 用户已经被锁定,请等 {0} 分钟后再尝试登录,或者找管理员解锁! res = new LogonResult(false, MessageFormat.format(getThisI18n("userIsLockedPleaseWaitSomeTimeToTry"), remainTime)); } } return res; } // 用户名密码正常,但有可能是停用状态 if(userObj != null && userObj.getStatus() == 1){ // 您的帐户已被停用,请联系管理员! return new LogonResult(false, getThisI18n("userIsDisabled")); } // 正常登录 updateLogonInfo(userObj.getId(), true); rmcd.savelog(getThisI18n("logon")); res.setSuccess(true); res.setMessage(""); res.setLogonedUserObject(userObj); // add by xchao 2017.12.13 begin // 在登录结果中加入当前登录用户所代表的VCIInvationInfo对象 res.setInvocationInfo(rmcd.getLogonedUserInvocationInfo(userObj, getClientInfo(clientIP), forBS)); // add by xchao 2017.12.13 end // 正常登录成功后的其它消息 res = checkOtherMessage(userName, existUserObj, userObj, pwdStgObj, res); return res; } private LogonResult checkOtherMessage( String userName, UserObject existUserObj, UserObject userObj, PasswordStrategyObject pwdStgObj, LogonResult res) throws VCIError, VCIException { if(RightControlUtil.isAdminOrDeveloperOrRoot(userName)){ return res; } int actualType = 0; int mimacelue = pwdStgObj.getRequiredType(); //判断密码属于哪种密码策略 CombinationObject[] combinationObjs = rmcd.fetchCombinationsByPstId(pwdStgObj.getId()); for (CombinationObject combObj : combinationObjs){ List list = new ArrayList(); CombinationValueObject[] combValObj = rmcd.fetchCombinationValuesByParentId(combObj.getId()); for (CombinationValueObject obj : combValObj){ list.add(obj.getValue()); } for (int i = 0 ; i < userObj.getPwd().length() ;i ++){ String a = ""+userObj.getPwd().charAt(i); if (list.contains(a)){ actualType +=1 ; break; } } } if (!("".equals(pwdStgObj.getId()))) {// 密码策略是否为空 defaultWrongNum = pwdStgObj.getRetryTime(); // 获取密码策略规定的错误登录次数 defaultLogonTime = pwdStgObj.getLockTime(); // 获取密码策略规定的锁定时间 dafaultOverdueDay = pwdStgObj.getOverdueDay(); // 获取密码规则的过期天数 dafaultRemideDay = pwdStgObj.getRemideDay(); // 获取密码策略规定的密码快过期提醒天数(提前xx天开始提醒该修改密码) } long pwdUpdateTime = userObj.getPwdUpdateTime(); long systemTime = rmcd.getSystemTime(); int date = compare_time(pwdUpdateTime, systemTime, false); //if ("1970-01-01 00:00:00.0".equals(pwdUpdateTime.toString())) { if (0 == pwdUpdateTime) { // 您的密码是管理员初始的密码,需要修改密码才能进行其它操作! res.setOtherMessage(getThisI18n("userPwdIsInitPleaseChange")); res.setNeedChangePassword(true); } else if (date > dafaultOverdueDay && userObj.getUserType() >= 1) { // 您的密码已经过期,请进行修改! res.setOtherMessage(getThisI18n("userPwdIsExpiredPleaseChange")); res.setNeedChangePassword(true); } else if (actualType < mimacelue) { // 您的密码策略已经修改,需要修改密码才能进行其它操作! res.setOtherMessage(getThisI18n("userPwdStagIsUpdatePleaseChange")); res.setNeedChangePassword(true); } else if ((dafaultOverdueDay > date) && (dafaultOverdueDay - date <= dafaultRemideDay) && userObj.getUserType() >= 1) { int pwValidity = dafaultOverdueDay - date; // 您的密码有效期还有" + pwValidity + "天,请注意修改! res.setOtherMessage(MessageFormat.format(getThisI18n("userPwdHasSomeDayExpire"), pwValidity)); res.setNeedChangePassword(false); } else if (RightControlUtil.isThreeAdmin(userName) && checkLogSpaced()) { // 日志存储将满,请及时清理! res.setOtherMessage(getThisI18n("logDataIsTooMuch")); res.setNeedChangePassword(false); } return res; } private UserEntityObject getUserEntityObject(String userName, String clientIP) { UserEntityObject obj = new UserEntityObject(); obj.setUserName(userName); obj.setIp(clientIP); // 登录模块 obj.setModules(getThisI18n("logonModule")); return obj; } /** * 日志空间是否将满 * * @return * @throws VCIError * @throws VCIException */ private boolean checkLogSpaced() throws VCIError, VCIException { DataSourceInfo dsInfo = ClientSession.getFrameworkService() .getDataSourceInfo();// 系统数据信息 AppConfigDetailObject logMaxCount = new AppConfigDetailClientDelegate( null).getAppConfigDetailByKey("LogMaxCount"); String logMaxCountValue = logMaxCount.getValue();// 系统日志最大条数 if(logMaxCountValue.equals("")||logMaxCountValue.length()<1){ logMaxCountValue="100000"; } String logCount =dsInfo.pllogCount;// 系统日志实际条数 float logRate = Float.parseFloat(logCount) / Float.parseFloat(logMaxCountValue); if (logRate >= 0.9) { return true; } return false; } /** * *

* 根据当前登录用户名和密码查询系统是否有此用户 *

* * @time 2013-3-19 * @return 当前用户对象 * @throws VCIException * 查询过程过发生异常 */ private UserObject checkLoginToSystem(String userName, String passWord, String clientIP) throws VCIException { String desPassword = passWord; /* * if(!(RightControlUtil.isAdminOrDeveloper(userName))){ *//** * 将登录界面中输入的密码加密 */ /* * ThreeDES des = new ThreeDES();// 实例化一个对像 * des.getKey("daliantan0v0");// 生成密匙 desPassword = * des.getEncString(password);// 加密字符串,返回String的密文 } */ return rmcd.checkLogin(userName, desPassword, getClientInfo(clientIP)); } private ClientInfo getClientInfo(String clientIP){ ClientInfo client = new ClientInfo(); client.setIp(clientIP); return client; } /** * 更新用户的登录信息。成功登录,错误次数改为0,登录时间改为当前时间; 登录失败,错误次数加1,登录时间改为当前时间。 * * @param userId * @param flag * @throws VCIError */ private void updateLogonInfo(String userId, boolean flag) throws VCIException { rmcd.updateLogonInfo(userId, flag); } /** * 根据登录的用户名获取将要被锁的账户 * * @return * @throws VCIError */ private UserObject getUserObjToLock(String userName) throws VCIException { return rmcd.getUserObjToLock(userName); } /** * 根据用户获取账户登录信息 * * @param userId * @return * @throws VCIError */ private UserLogonObject getUserLogonObj(String userId) throws VCIException { return rmcd.getUserLogonObj(userId); } /** * 求两个时间相隔多久 * * @param DATE1 * @param DATE2 * @param flag * @return */ private int compare_time(long DATE1, long DATE2, boolean flag) { // SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSSS"); Date dt1 = null; //dt1 = df.parse(DATE1); dt1 = new Date(DATE1); // 相差的毫秒数 long millis = DATE2 - dt1.getTime(); // 相差的秒数 long secnods = millis / 1000; // 相差的天数 long days = secnods / (24*60*60); // 相差的小时数 long hours = secnods / (60*60); // 相差的分钟数 long minutes = secnods / (60); if(flag){ return (int)minutes; } else { return (int)days; } // long seconds = (DATE2 - dt1.getTime()) / 1000; // long date = seconds / (24 * 60 * 60); // 相差的天数 // long hour = (seconds - date * 24 * 60 * 60) / (60 * 60);// 相差的小时数 // long minut = (seconds - date * 24 * 60 * 60 - hour * 60 * 60) / (60);// 相差的分钟数 // // long second = (seconds-date*24*60*60-hour*60*60-minut*60);//相差的秒数 // if (flag) { // return (int) (minut); // 返回分钟数 // } else { // return (int) (date); // 返回天数 // } } }