diff --git a/src/main/java/egovframework/com/uat/uia/web/EgovLoginController.java b/src/main/java/egovframework/com/uat/uia/web/EgovLoginController.java index 521c718..cf6782e 100644 --- a/src/main/java/egovframework/com/uat/uia/web/EgovLoginController.java +++ b/src/main/java/egovframework/com/uat/uia/web/EgovLoginController.java @@ -3,7 +3,7 @@ package egovframework.com.uat.uia.web; import java.io.UnsupportedEncodingException; import java.util.HashMap; import java.util.List; -import java.util.Random; +import java.security.SecureRandom; import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; @@ -441,7 +441,9 @@ public class EgovLoginController { char[] charaters = {'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','0','1','2','3','4','5','6','7','8','9'}; StringBuffer sb = new StringBuffer(); - Random rn = new Random(); + // [보안/SER-004] 휴면 활성화 메일 토큰 난수를 예측 가능한 java.util.Random 에서 + // 암호학적 안전 난수(SecureRandom)로 교체(CWE-330). 토큰 재현·추측 방지. + SecureRandom rn = new SecureRandom(); for( int i = 0 ; i < 20 ; i++ ){ sb.append( charaters[ rn.nextInt( charaters.length ) ] ); } @@ -461,14 +463,30 @@ public class EgovLoginController { /** * 휴면계정 활성화 + * + * [보안/SER-004] 인증 없는 휴면계정 해제 차단. + * 종전: 요청 파라미터 mber_id 만으로 즉시 deleteDiapause 실행 → 아이디만 알면 + * 제3자가 임의 계정의 휴면을 해제할 수 있었다(본인확인 부재, CWE-306). + * 변경: 파라미터를 신뢰하지 않고, ID/PW 인증에 성공해야만 세션에 적재되는 + * diapauseVO(EgovSpringSecurityLoginFilter/diapauseLogin 에서 setAttribute)의 + * mber_id 로만 해제한다. 프론트 경로(releaseDiapauseAjax)가 이메일 토큰을 + * 검증하는 것과 동일하게, 모바일 경로는 '로그인 세션' 을 본인확인 근거로 삼는다. + * 세션 부재·불일치 시 해제하지 않고 resCode=002 로 거부, 성공 시 1회성 소거. */ @RequestMapping(value = "/uat/uia/actionDiapause.do") public String actionDiapause(HttpServletRequest request, HttpServletResponse response - ,@RequestParam(value="mber_id", required=true) String mber_id ,ModelMap model) throws Exception { + LoginVO diapauseVO = (LoginVO) request.getSession().getAttribute("diapauseVO"); + if (diapauseVO == null || diapauseVO.getMber_id() == null || "".equals(diapauseVO.getMber_id())) { + // 로그인(본인확인) 없이 직접 호출된 요청 — 해제 거부 + model.addAttribute("resCode", "002"); + return JSON; + } LoginVO vo = new LoginVO(); - vo.setMber_id(mber_id); + vo.setMber_id(diapauseVO.getMber_id()); loginService.deleteDiapause(vo); + request.getSession().removeAttribute("diapauseVO"); // 재사용 방지 + model.addAttribute("resCode", "001"); return JSON; } diff --git a/src/main/webapp/WEB-INF/jsp/site/mbl/member/EgovDiapause.jsp b/src/main/webapp/WEB-INF/jsp/site/mbl/member/EgovDiapause.jsp index 984a7b4..7fcab64 100644 --- a/src/main/webapp/WEB-INF/jsp/site/mbl/member/EgovDiapause.jsp +++ b/src/main/webapp/WEB-INF/jsp/site/mbl/member/EgovDiapause.jsp @@ -26,14 +26,19 @@ function actionDiapause() { $.ajax({ url : "/uat/uia/actionDiapause.do", type : "POST", - data : {"mber_id" : $("#mber_id").val(), "esntl_id" : $("#esntl_id").val()}, dataType : "json", - success:function(object){ - alert("휴먼계정이 해제 되었습니다. \n다시 로그인 하세요."); + success:function(object){ + // [보안] 서버가 로그인 세션(diapauseVO)으로 본인확인 후 해제한다. + // resCode 001=성공, 002=본인확인 실패(세션 만료 등) → 재로그인 유도. + if(object && object.resCode === "001"){ + alert("휴면계정이 해제 되었습니다. \n다시 로그인 하세요."); + } else { + alert("본인확인이 만료되었습니다. \n다시 로그인 후 시도해 주세요."); + } location.href = "/uat/uia/egovLoginUsr.do"; - }, + }, error:function(xhr,status,error){alert(status);} - }); + }); } //-->