This commit is contained in:
@@ -184,8 +184,9 @@ function getEndTime(){
|
||||
</td>
|
||||
<th style="width:180px;"><%= localeMessage.getString("auditLogMan.remoteAddress") %></th>
|
||||
<td><input type="text" name="searchRemoteAddress" value="${param.searchRemoteAddress}" style="width:100%"></td>
|
||||
<th style="width:180px;"></th>
|
||||
<th style="width:180px;"><%= localeMessage.getString("auditLogMan.parameters") %></th>
|
||||
<td>
|
||||
<input type="text" name="searchParameters" value="${param.searchParameters}" style="width:100%">
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
@@ -18,6 +18,16 @@
|
||||
<script language="javascript" >
|
||||
var url = '<c:url value="/common/acl/user/userMan.json" />';
|
||||
var url_view = '<c:url value="/common/acl/user/userMan.view" />';
|
||||
|
||||
function userStatusFormat (cellvalue){
|
||||
if ( cellvalue == '1' ){
|
||||
return '<%= localeMessage.getString("code.normal") %>';
|
||||
}else if ( cellvalue == '2' ) {
|
||||
return '<span style="color:red"><%= localeMessage.getString("code.lock") %></span>';
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
$(document).ready(function() {
|
||||
var gridPostData = getSearchForJqgrid("cmd","LIST"); //jqgrid에서는 object 로
|
||||
$('#grid').jqGrid({
|
||||
@@ -28,6 +38,7 @@ $(document).ready(function() {
|
||||
colNames:['<%= localeMessage.getString("login.userId") %>',
|
||||
'<%= localeMessage.getString("user.name") %>',
|
||||
'<%= localeMessage.getString("user.roleName") %>',
|
||||
'<%= localeMessage.getString("user.status") %>',
|
||||
'<%= localeMessage.getString("user.createOn") %>',
|
||||
'<%= localeMessage.getString("user.depart") %>',
|
||||
'<%= localeMessage.getString("user.teamName") %>',
|
||||
@@ -37,6 +48,7 @@ $(document).ready(function() {
|
||||
{ name : 'USERID' , align:'center' ,sortable:false },
|
||||
{ name : 'USERNAME' , align:'center' },
|
||||
{ name : 'ROLEIDNFINAME' , align:'center' },
|
||||
{ name : 'STATUS' , align:'center', formatter: userStatusFormat },
|
||||
{ name : 'LASTAMNDYMS' , align:'center', formatter: timeStampFormat },
|
||||
{ name : 'DVSNNAME' , align:'center', hidden: true },
|
||||
{ name : 'TEAMNAME' , align:'center', hidden: true },
|
||||
|
||||
@@ -216,6 +216,7 @@ $(document).ready(function() {
|
||||
dataType:"json",
|
||||
data:{cmd: 'UPDATE_PASSWORD', userId : $("input[name=userId]").val()},
|
||||
success:function(json){
|
||||
$('select[name="status"]').val("1")
|
||||
alert(json.result);
|
||||
},
|
||||
error:function(e){
|
||||
@@ -277,10 +278,10 @@ $(document).ready(function() {
|
||||
<table class="table_row" cellspacing="0">
|
||||
<input type="hidden" name="jobclcd">
|
||||
<tr>
|
||||
<th style="width:180px;"><%= localeMessage.getString("login.userId") %></th><td ><input type="text" name="userId"/> </td>
|
||||
<th style="width:180px;"><%= localeMessage.getString("login.userId") %> <span class=\"required-mark\">*</span></th><td ><input type="text" name="userId"/> </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><%= localeMessage.getString("user.name") %> </th><td><input type="text" name="userName" /></td>
|
||||
<th><%= localeMessage.getString("user.name") %> <span class=\"required-mark\">*</span></th><td><input type="text" name="userName" /></td>
|
||||
</tr>
|
||||
<tr class="datailT">
|
||||
<th><%= localeMessage.getString("user.auth") %> </th><td><input type="text" name="roleidnfiname" /></td>
|
||||
@@ -317,7 +318,6 @@ $(document).ready(function() {
|
||||
<td>
|
||||
<div class="select-style">
|
||||
<select name="status">
|
||||
<option value=""><%= localeMessage.getString("code.normal") %></option>
|
||||
<option value="1"><%= localeMessage.getString("code.normal") %></option>
|
||||
<option value="2"><%= localeMessage.getString("code.lock") %></option>
|
||||
</select>
|
||||
|
||||
+3
@@ -51,6 +51,9 @@ public class AuditLogPageRepositoryImpl implements AuditLogPageRepository {
|
||||
if (StringUtils.isNotBlank(command.getSearchRemoteAddress())) {
|
||||
jpaQuery.where(qAuditLogEntity.remoteAddress.containsIgnoreCase(command.getSearchRemoteAddress()));
|
||||
}
|
||||
if (StringUtils.isNotBlank(command.getSearchParameters())) {
|
||||
jpaQuery.where(qAuditLogEntity.parameters.containsIgnoreCase(command.getSearchParameters()));
|
||||
}
|
||||
|
||||
long totalCount = jpaQuery.fetchOne();
|
||||
List<AuditLogEntity> auditLogs = jpaQuery
|
||||
|
||||
+1
@@ -18,6 +18,7 @@ public class SelectListAuditLogCommand {
|
||||
|
||||
private String searchUserId;
|
||||
private String searchRemoteAddress;
|
||||
private String searchParameters;
|
||||
|
||||
@JsonFormat(pattern = "yyyyMMddHHmmss")
|
||||
@DateTimeFormat(pattern = "yyyyMMddHHmmss")
|
||||
|
||||
@@ -42,7 +42,7 @@ import lombok.RequiredArgsConstructor;
|
||||
@RequiredArgsConstructor
|
||||
public class UserManService extends BaseService {
|
||||
|
||||
|
||||
private static final String USER_STATUS_NORMAL = "1";
|
||||
|
||||
private final UserInfoService userInfoService;
|
||||
private final UserRoleService userRoleService;
|
||||
@@ -100,6 +100,7 @@ public class UserManService extends BaseService {
|
||||
|
||||
UserInfo userInfo = userUIMapper.toEntity(userUI);
|
||||
userInfo.setRoleidnfiname(CommonConstants.DEPT_DEVELOPER);
|
||||
userInfo.setStatus(USER_STATUS_NORMAL);
|
||||
|
||||
String subfix = monitoringContext.getStringProperty(MonitoringContext.RMS_PASSWORD_INIT_SUBFIX, "@!");
|
||||
|
||||
@@ -133,6 +134,12 @@ public class UserManService extends BaseService {
|
||||
public void update(UserUI userUI) {
|
||||
UserInfo userInfo = userInfoService.getById(userUI.getUserId());
|
||||
userUIMapper.updateToEntity(userUI, userInfo);
|
||||
|
||||
// 계정상태를 정상으로 저장하면 로그인 실패횟수 초기화
|
||||
if (USER_STATUS_NORMAL.equals(userInfo.getStatus())) {
|
||||
userInfo.setLoginfailcount(0);
|
||||
}
|
||||
|
||||
userInfoService.save(userInfo);
|
||||
}
|
||||
|
||||
@@ -148,6 +155,11 @@ public class UserManService extends BaseService {
|
||||
UserInfo userInfo = userInfoService.getById(userUI.getUserId());
|
||||
userInfo.setPassword(DamoManager.getInstance().hash(DamoManager.SHA256, userUI.getUserId()+subfix));
|
||||
userUIMapper.updateToEntity(userUI, userInfo);
|
||||
|
||||
// 비밀번호 초기화 시 계정상태를 정상으로 변경하고 로그인 실패횟수 초기화
|
||||
userInfo.setLoginfailcount(0);
|
||||
userInfo.setStatus(USER_STATUS_NORMAL);
|
||||
|
||||
userInfoService.save(userInfo);
|
||||
}
|
||||
|
||||
|
||||
@@ -266,6 +266,9 @@ public interface MonitoringContext {
|
||||
//비밀번호 초기화 접미사
|
||||
public static final String RMS_PASSWORD_INIT_SUBFIX = "rms.password.init.subfix";
|
||||
|
||||
// 최대 로그인 실패 허용횟수 (0이면 계정 잠금 미적용)
|
||||
public static final String RMS_PASSWORD_FAIL_COUNT = "rms.password.fail.count";
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -64,6 +64,9 @@ public class MainController implements InterceptorSkipController {
|
||||
private static final String REDIRECT_LOGIN_URL = "redirect:/emergency.jsp";
|
||||
private static final String REDIRECT_CHANGE_PASSWORD_URL = "redirect:/emergency.jsp";
|
||||
|
||||
private static final String USER_STATUS_LOCKED = "2";
|
||||
private static final int DEFAULT_MAX_LOGIN_FAIL_COUNT = 5;
|
||||
|
||||
private final LocaleMessage localeMessage;
|
||||
private final MonitoringContext monitoringContext;
|
||||
|
||||
@@ -160,7 +163,7 @@ public class MainController implements InterceptorSkipController {
|
||||
session.removeAttribute(RESULT_MSG);
|
||||
return LoginResponseDto.builder()
|
||||
.success(false)
|
||||
.errorMessage(errorMsg != null ? errorMsg : "로그인에 실패했습니다.")
|
||||
.errorMessage(toAlertMessage(errorMsg != null ? errorMsg : "로그인에 실패했습니다."))
|
||||
.build();
|
||||
}
|
||||
|
||||
@@ -345,9 +348,19 @@ public class MainController implements InterceptorSkipController {
|
||||
|
||||
//logger.info("사용자 계정 상태: " + userInfo.getStatus());
|
||||
|
||||
if ( userInfo.getStatus() != null && "2".equals(userInfo.getStatus()) ) {
|
||||
if ( USER_STATUS_LOCKED.equals(userInfo.getStatus()) ) {
|
||||
int maxLoginFailCount = getMaxLoginFailCount();
|
||||
boolean lockedByFailCount = maxLoginFailCount > 0
|
||||
&& userInfo.getLoginfailcount() != null
|
||||
&& userInfo.getLoginfailcount() >= maxLoginFailCount;
|
||||
|
||||
if (lockedByFailCount) {
|
||||
setLoginFailure(request, session, "login.accountlocked1",
|
||||
"login.accountlocked2", String.valueOf(maxLoginFailCount));
|
||||
} else {
|
||||
setLoginFailure(request, session, "login.checkstatus1",
|
||||
"login.checkstatus2");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -374,8 +387,9 @@ public class MainController implements InterceptorSkipController {
|
||||
/* 기존로직 - LDAP 사용 x */
|
||||
if (!userInfo.getPassword().equals(DamoManager.getInstance().hash(DamoManager.SHA256, dto.getPassword()))) {
|
||||
// password 다름.
|
||||
int failCount = increaseLoginFailCount(userInfo);
|
||||
setLoginFailure(request, session, "login.loginfail1",
|
||||
"login.loginfail2");
|
||||
"login.loginfail2", failCount);
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
@@ -389,8 +403,9 @@ public class MainController implements InterceptorSkipController {
|
||||
//if (!authenticate(userInfo.getUserid(), dto.getPassword())) {
|
||||
if (!authenticate(userInfo.getUserid(), password)) {
|
||||
// password 다름.
|
||||
int failCount = increaseLoginFailCount(userInfo);
|
||||
setLoginFailure(request, session, "login.loginfail1",
|
||||
"login.loginfail2");
|
||||
"login.loginfail2", failCount);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -432,6 +447,27 @@ public class MainController implements InterceptorSkipController {
|
||||
return userInfo;
|
||||
}
|
||||
|
||||
// 최대 로그인 실패 허용횟수 조회 (rms.password.fail.count, 0이면 계정 잠금 미적용)
|
||||
private int getMaxLoginFailCount() {
|
||||
return monitoringContext.getIntProperty(
|
||||
MonitoringContext.RMS_PASSWORD_FAIL_COUNT, DEFAULT_MAX_LOGIN_FAIL_COUNT);
|
||||
}
|
||||
|
||||
// 로그인 실패 횟수 증가, 임계치 도달 시 계정 잠금
|
||||
private int increaseLoginFailCount(UserInfo userInfo) {
|
||||
int failCount = (userInfo.getLoginfailcount() == null ? 0 : userInfo.getLoginfailcount()) + 1;
|
||||
userInfo.setLoginfailcount(failCount);
|
||||
|
||||
int maxLoginFailCount = getMaxLoginFailCount();
|
||||
if (maxLoginFailCount > 0 && failCount >= maxLoginFailCount) {
|
||||
userInfo.setStatus(USER_STATUS_LOCKED);
|
||||
logger.warn("로그인 " + maxLoginFailCount + "회 이상 실패로 계정 잠금 처리: " + userInfo.getUserid());
|
||||
}
|
||||
|
||||
userInfoService.save(userInfo);
|
||||
return failCount;
|
||||
}
|
||||
|
||||
// LDAP
|
||||
public boolean authenticate(String userId, String password) {
|
||||
String LDAP_URL = monitoringPropertyService.getPrpty2ValById("Monitoring", "ldap.domain");
|
||||
@@ -496,6 +532,7 @@ public class MainController implements InterceptorSkipController {
|
||||
String lastLoginIp = IpUtil.getClientIp(request);
|
||||
userInfo.setLastloginyms(LocalDateTime.now());
|
||||
userInfo.setLastloginip(lastLoginIp);
|
||||
userInfo.setLoginfailcount(0);
|
||||
userInfoService.save(userInfo);
|
||||
}
|
||||
|
||||
@@ -556,12 +593,32 @@ public class MainController implements InterceptorSkipController {
|
||||
return "redirect:/common/errors/errorLogon.jsp";
|
||||
}
|
||||
|
||||
// HTML 개행 태그(<BR/> 등)를 JS alert용 개행문자로 변환
|
||||
private String toAlertMessage(String message) {
|
||||
return message.replaceAll("(?i)<br\\s*/?>", "\n");
|
||||
}
|
||||
|
||||
// 로그인 실패 시 로그 기록, 세션에 실패 메시지 설정
|
||||
private void setLoginFailure(HttpServletRequest request,
|
||||
HttpSession session, String logKey, String msgKey) {
|
||||
HttpSession session, String logKey, String msgKey,
|
||||
String... msgArgs) {
|
||||
UserAccessLogger.log(request, LOG_CATEGORY_LOGIN, "F",
|
||||
localeMessage.getString(logKey));
|
||||
session.setAttribute(RESULT_MSG, localeMessage.getString(msgKey));
|
||||
session.setAttribute(RESULT_MSG, localeMessage.getString(msgKey, msgArgs));
|
||||
}
|
||||
|
||||
// 로그인 실패 시 로그 기록, 세션에 실패 메시지(실패 횟수 포함) 설정
|
||||
private void setLoginFailure(HttpServletRequest request,
|
||||
HttpSession session, String logKey, String msgKey,
|
||||
int failCount) {
|
||||
UserAccessLogger.log(request, LOG_CATEGORY_LOGIN, "F",
|
||||
localeMessage.getString(logKey));
|
||||
String msg = localeMessage.getString(msgKey);
|
||||
int maxLoginFailCount = getMaxLoginFailCount();
|
||||
if (maxLoginFailCount > 0) {
|
||||
msg += " (" + failCount + "/" + maxLoginFailCount + ")";
|
||||
}
|
||||
session.setAttribute(RESULT_MSG, msg);
|
||||
}
|
||||
|
||||
// 서비스 타입 검증
|
||||
|
||||
@@ -19,6 +19,7 @@ import com.eactive.eai.rms.data.entity.onl.bzwkdstcd.UserBusinessService;
|
||||
import com.eactive.eai.rms.data.entity.onl.layout.LayoutItemEMSRepository;
|
||||
import com.eactive.eai.rms.data.entity.onl.layout.LayoutService;
|
||||
import com.eactive.eai.rms.onl.manage.rule.layoutsync.LayoutSyncVo;
|
||||
import com.eactive.eai.transformer.layout.Item;
|
||||
|
||||
@Repository("layoutDao")
|
||||
@SuppressWarnings("unchecked")
|
||||
@@ -122,8 +123,25 @@ public class LayoutDao extends SqlMapClientTemplateDao {
|
||||
entity.setLoutitempathname((String) param.get("loutItemPathName"));
|
||||
entity.setLoutitemlencnt((Integer) param.get("loutItemLenCnt"));
|
||||
entity.setLoutitemrefinfo((String) param.get("loutItemRefInfo"));
|
||||
entity.setLoutitemrefinfo2((String) param.get("loutItemRefInfo2"));
|
||||
entity.setLoutitemoccurptrndstcd((String) param.get("loutItemOccurPtrnDstcd"));
|
||||
|
||||
// djb cumstom : 반복 참조 필드에 .이 포함되서 오면 .이후의 값만 저장
|
||||
String loutItemRefInfo2 = (String) param.get("loutItemRefInfo2");
|
||||
if (loutItemRefInfo2 != null && loutItemRefInfo2.indexOf(".") > -1) {
|
||||
loutItemRefInfo2 = loutItemRefInfo2.substring(loutItemRefInfo2.lastIndexOf(".")+1);
|
||||
}
|
||||
entity.setLoutitemrefinfo2(loutItemRefInfo2);
|
||||
|
||||
// djb custom : GRIP(=GROUP)이고 반복횟수=1 일때는 반복횟수 넣지않는다. ==> GROUP으로 처리
|
||||
Integer loutItemNodePtrnIDName = (Integer) param.get("loutItemNodePtrnIDName");
|
||||
String loutItemOccurPtrnDstcd = (String) param.get("loutItemOccurPtrnDstcd");
|
||||
if (loutItemNodePtrnIDName != null) {
|
||||
if (loutItemNodePtrnIDName == Item.NODE_GROUP && "1".equals(loutItemOccurPtrnDstcd)) {
|
||||
loutItemOccurPtrnDstcd = "";
|
||||
}
|
||||
}
|
||||
entity.setLoutitemoccurptrndstcd(loutItemOccurPtrnDstcd);
|
||||
|
||||
|
||||
entity.setLoutitemmaxoccurnoitm((Integer) param.get("loutItemMaxOccurNoitm"));
|
||||
entity.setLoutitemminoccurnoitm((Integer) param.get("loutItemMinOccurNoitm"));
|
||||
entity.setLoutitembascval((String) param.get("loutItemBascVal"));
|
||||
|
||||
+4
-4
@@ -934,9 +934,9 @@ public class LayoutSyncController extends OnlBaseAnnotationController implements
|
||||
|
||||
service.deleteLayout(vo);
|
||||
|
||||
CommonCommand commonCommand = new CommonCommand("com.eactive.eai.agent.transformer.RemoveLayoutCommand",vo.get("loutName"));
|
||||
HashMap<String,String> result = AgentParserUtils.parse(commonCommand, agentUtilService,"prcssRslt","prcssRsltCmnt");
|
||||
param.putAll(result);
|
||||
// CommonCommand commonCommand = new CommonCommand("com.eactive.eai.agent.transformer.RemoveLayoutCommand",vo.get("loutName"));
|
||||
// HashMap<String,String> result = AgentParserUtils.parse(commonCommand, agentUtilService,"prcssRslt","prcssRsltCmnt");
|
||||
// param.putAll(result);
|
||||
|
||||
service.addLayoutSyncLog(param);
|
||||
} else {
|
||||
@@ -1024,7 +1024,7 @@ public class LayoutSyncController extends OnlBaseAnnotationController implements
|
||||
|
||||
service.insertLayout(vo, list); //FIXME : 스키마 변경 룰 적용해야 함
|
||||
|
||||
//Djb custom 서버연동 제외 2026.07.22 jwh
|
||||
//Djb custom 서버연동 제외
|
||||
// CommonCommand commonCommand = new CommonCommand("com.eactive.eai.agent.transformer.ReloadLayoutCommand",vo.get("loutName"));
|
||||
// HashMap<String,String> result = AgentParserUtils.parse(commonCommand, agentUtilService,"prcssRslt","prcssRsltCmnt");
|
||||
// param.putAll(result);
|
||||
|
||||
@@ -1200,6 +1200,8 @@ login.failcountover2 = You have had three password failures. <B
|
||||
login.grantfail1 = Failed to initialize user credential information.
|
||||
login.grantfail2 = Logon Error:<BR>Failed to initialize user credential information.
|
||||
login.loginfail1 = Login failed. Please check your login information.
|
||||
login.accountlocked1 = Account locked due to {0} or more login failures. Please contact your administrator.
|
||||
login.accountlocked2 = Account locked due to {0} or more login failures.<BR/> Please contact your administrator.
|
||||
login.loginfail2 = Login failed.<BR/>Please check your login information.
|
||||
login.logonaccount = Logon account
|
||||
login.logout = Logout
|
||||
|
||||
@@ -1346,6 +1346,8 @@ login.failcountover2 = You have had three password failures. <B
|
||||
login.grantfail1 = Failed to initialize user credential information.
|
||||
login.grantfail2 = Logon Error:<BR>Failed to initialize user credential information.
|
||||
login.loginfail1 = Login failed. Please check your login information.
|
||||
login.accountlocked1 = Account locked due to {0} or more login failures. Please contact your administrator.
|
||||
login.accountlocked2 = Account locked due to {0} or more login failures.<BR/> Please contact your administrator.
|
||||
login.loginfail2 = Login failed.<BR/>Please check your login information.
|
||||
login.logonaccount = Logon account
|
||||
login.logout = Logout
|
||||
|
||||
@@ -1426,6 +1426,8 @@ login.loginfail1 = \uC0AC\uC6A9\uC790ID \uB610\uB294 \uBE44
|
||||
login.loginfail2 = \uC0AC\uC6A9\uC790ID \uB610\uB294 \uBE44\uBC00\uBC88\uD638 \uC785\uB825 \uC2E4\uD328\uC785\uB2C8\uB2E4.<BR/> \uB85C\uADF8\uC778\uC815\uBCF4\uB97C \uD655\uC778\uD558\uC138\uC694.
|
||||
login.checkstatus1 = \uC7A5\uAE30(90\uC77C)\uBBF8\uC0AC\uC6A9 \uACC4\uC815\uC785\uB2C8\uB2E4. \uB2F4\uB2F9\uC790\uC5D0\uAC8C \uBB38\uC758\uD558\uC138\uC694.
|
||||
login.checkstatus2 = \uC7A5\uAE30(90\uC77C)\uBBF8\uC0AC\uC6A9 \uACC4\uC815\uC785\uB2C8\uB2E4.<BR/> \uB2F4\uB2F9\uC790\uC5D0\uAC8C \uBB38\uC758\uD558\uC138\uC694.
|
||||
login.accountlocked1 = \uB85C\uADF8\uC778 {0}\uD68C \uC774\uC0C1 \uC2E4\uD328\uB85C \uACC4\uC815\uC774 \uC7A0\uACBC\uC2B5\uB2C8\uB2E4. \uAD00\uB9AC\uC790\uC5D0\uAC8C \uBB38\uC758\uD558\uC138\uC694.
|
||||
login.accountlocked2 = \uB85C\uADF8\uC778 {0}\uD68C \uC774\uC0C1 \uC2E4\uD328\uB85C \uACC4\uC815\uC774 \uC7A0\uACBC\uC2B5\uB2C8\uB2E4.<BR/> \uAD00\uB9AC\uC790\uC5D0\uAC8C \uBB38\uC758\uD558\uC138\uC694.
|
||||
login.logonaccount = \uB85C\uADF8\uC628\uACC4\uC815
|
||||
login.logout = \uB85C\uADF8\uC544\uC6C3
|
||||
login.password = \uBE44\uBC00\uBC88\uD638
|
||||
|
||||
Reference in New Issue
Block a user