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.client.ui.swing.VCIOptionPane;
|
import com.vci.corba.common.VCIError;
|
import com.vci.corba.framework.data.DataSourceInfo;
|
import com.vci.mw.ClientContextVariable;
|
|
/**
|
* 通用的用户登录处理逻辑
|
*
|
* <p>Title: </p>
|
* <p>Description: </p>
|
* <p>Copyright: Copyright (c) 2016</p>
|
* <p>Company: VCI</p>
|
* @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;
|
}
|
|
|
if (!("".equals(pwdStgObj.getId()))) {// 密码策略是否为空
|
defaultWrongNum = pwdStgObj.getRetryTime(); // 获取密码策略规定的错误登录次数
|
defaultLogonTime = pwdStgObj.getLockTime(); // 获取密码策略规定的锁定时间
|
dafaultOverdueDay = pwdStgObj.getOverdueDay(); // 获取密码规则的过期天数
|
dafaultRemideDay = pwdStgObj.getRemideDay(); // 获取密码策略规定的密码快过期提醒天数(提前xx天开始提醒该修改密码)
|
}
|
|
String password = userObj.getPwd();
|
int requiredType = pwdStgObj.getRequiredType(); // 必填种类
|
int containsTypes = pwdStgObj.getCharTypes();// 包含字符类型
|
|
//判断密码属于哪种密码策略
|
// CombinationObject[] combinationObjs = rmcd.fetchCombinationsByPstId(pwdStgObj.getId());
|
// for (CombinationObject combObj : combinationObjs){
|
// List<String> list = new ArrayList<String>();
|
// 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;
|
// }
|
// }
|
// }
|
int actualTypes = 0;
|
int typeCount = 0;
|
{
|
|
String symbol = "[ _`~!@#$%^&*()-+={[}]|\\'\":;,.<>/?";
|
|
for (int i = 0 ; i < password.length() ;i ++){
|
char c = password.charAt(i);
|
if (Character.isDigit(c))
|
actualTypes |= 0x01;
|
else if (Character.isLowerCase(c))
|
actualTypes |= 0x02;
|
else if (Character.isUpperCase(c))
|
actualTypes |= 0x04;
|
else if (symbol.indexOf(c) > -1)
|
actualTypes |= 0x08;
|
}
|
|
for (int i = 0; i < 4; i++) {
|
int type = (int)Math.pow(2, i);
|
if ((actualTypes & type) == type)
|
typeCount++;
|
}
|
|
if ((actualTypes & containsTypes) != actualTypes || typeCount < requiredType){
|
res.setOtherMessage(getThisI18n("userPwdStagIsUpdatePleaseChange"));
|
res.setNeedChangePassword(true);
|
}
|
}
|
|
|
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) {
|
} else if ((actualTypes & containsTypes) != actualTypes || typeCount < requiredType){
|
// 您的密码策略已经修改,需要修改密码才能进行其它操作!
|
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;
|
}
|
|
|
/**
|
*
|
* <p>
|
* 根据当前登录用户名和密码查询系统是否有此用户
|
* </p>
|
*
|
* @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); // 返回天数
|
// }
|
}
|
|
|
}
|