jsshin 5 лет назад
Родитель
Сommit
be37c68edc

+ 20 - 0
src/main/java/com/style24/front/biz/dao/TsfCustomerDao.java

@@ -104,4 +104,24 @@ public interface TsfCustomerDao {
 	 * @since 2021. 03. 11
 	 */
 	String  getDeleteGoodsWish(int custNo);
+
+	/**
+	 * 본인인증 처리
+	 *
+	 * @param customer - 고객번호, ci
+	 * @return int - 업데이트 카운트
+	 * @author jsshin
+	 * @since 2021. 03. 11
+	 */
+	int updateCustomerCi(Customer customer);
+
+	/**
+	 * 비밀번호 변경 날짜 업데이트
+	 *
+	 * @param customer - 고객번호
+	 * @return int - 업데이트 카운트
+	 * @author jsshin
+	 * @since 2021. 03. 11
+	 */
+	int updatePasswordDate(Customer customer);
 }

+ 89 - 1
src/main/java/com/style24/front/biz/service/TsfCustomerService.java

@@ -77,7 +77,7 @@ public class TsfCustomerService {
 	}
 
 	/**
-	 * 고객정보찾기 -
+	 * 고객정보찾기
 	 *
 	 * @param custNo - 고객번호
 	 * @return Customer 고객정보
@@ -93,6 +93,23 @@ public class TsfCustomerService {
 		return coreCustomerService.getCustomerInfo(customer);
 	}
 
+	/**
+	 * 휴면고객 정보 찾기
+	 *
+	 * @param custNo - 고객번호
+	 * @return Customer 고객정보
+	 * @author jsshin
+	 * @since 2021. 03. 10
+	 */
+	public Customer getDormantCustomerFindByCustNo(Integer custNo) {
+		Customer customer = new Customer();
+		customer.setCustNo(custNo);
+		customer.setCustStat(TscConstants.CustStat.DORMANT.value());
+		customer.setSiteCd(TscConstants.Site.STYLE24.value());
+		customer.encryptData();
+		return coreCustomerService.getCustomerInfo(customer);
+	}
+
 
 	/**
 	 * 임시비밀번호 조회
@@ -673,10 +690,81 @@ public class TsfCustomerService {
 	 */
 	public GagaMap releaseDormantCustomer(Customer customer) {
 		GagaMap result = new GagaMap();
+
+		Customer custInfo = getDormantCustomerFindByCustNo(customer.getCustNo());
+
+		if (!customer.getCi().equals(custInfo.getCi())) {
+			result.setBoolean("isRelase", false);
+			result.setString("errorType", "DIFFERENT_CI"); // 계정이 등록된 CI랑 인증한 CI가 다를떄
+			return result;
+		}
+
 		customer.setRegNo(customer.getCustNo());
 		customer.setUpdNo(customer.getCustNo());
 		boolean isRelase = coreCustomerService.saveDormantCustomerRelease(customer);
 		result.setBoolean("isRelase", isRelase);
 		return result;
 	}
+
+	/**
+	 * 본인인증 처리
+	 *
+	 * @param customer - 본인인증키
+	 * @return GagaMap - 결과
+	 * @author jsshin
+	 * @since 2021. 03. 11
+	 */
+	public GagaMap saveCertification(Customer customer) {
+		GagaMap resultMap = new GagaMap();
+		customer.setRegNo(customer.getCustNo());
+		customer.setUpdNo(customer.getCustNo());
+		boolean isSuccess = false;
+		// CI 유효성 체크
+		Customer custInfo = getCustomerFindByCi(customer.getCi());
+		if (custInfo != null) {
+			TsfSession.setAttribute("maskingCustId", custInfo.getMaskingCustId());
+			resultMap.setBoolean("isSuccess", isSuccess);
+			return resultMap;
+		}
+
+		// 1.이력 쌓고
+		coreCustomerService.createCustomerHistory(customer);
+		// 2.CI 업데이트
+		int resultCnt = customerDao.updateCustomerCi(customer);
+		if (resultCnt > 0) {
+			isSuccess = true;
+		}
+		resultMap.setBoolean("isSuccess", isSuccess);
+
+		return resultMap;
+	}
+
+	/**
+	 * 비밀번호 변경 날짜 업데이트
+	 *
+	 * @param customer - 고객번호
+	 * @return GagaMap - 결과
+	 * @author jsshin
+	 * @since 2021. 03. 11
+	 */
+	public GagaMap updatePasswordDate(Customer customer) {
+		GagaMap resultMap = new GagaMap();
+		boolean isSuccess = false;
+		customer.setRegNo(customer.getCustNo());
+		customer.setUpdNo(customer.getCustNo());
+		customer.setPwdChangeDay(60); //30일간 안보여야 하기때문에 (오늘날짜 - 60) 처리
+
+		// 1.이력 쌓고
+		coreCustomerService.createCustomerHistory(customer);
+
+		// 2.비밀번호 변경일자 업데이트
+		int resultCnt = customerDao.updatePasswordDate(customer);
+		if (resultCnt > 0) {
+			isSuccess = true;
+		}
+
+		resultMap.setBoolean("isSuccess", isSuccess);
+
+		return resultMap;
+	}
 }

+ 91 - 7
src/main/java/com/style24/front/biz/web/TsfCustomerController.java

@@ -24,9 +24,11 @@ import com.style24.front.support.controller.TsfBaseController;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.web.bind.annotation.RequestParam;
 import org.springframework.web.bind.annotation.ResponseBody;
+import org.springframework.web.bind.support.SessionStatus;
 import org.springframework.web.servlet.ModelAndView;
 
 import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpSession;
 
 
 /**
@@ -234,10 +236,18 @@ public class TsfCustomerController extends TsfBaseController {
 	 * @author jsshin
 	 * @since 2021. 02. 17
 	 */
-	@GetMapping("password/change/form")
+	@GetMapping("/password/change/form")
 	public ModelAndView passwrodChangeForm(@RequestParam(value = "pageGb")String pageGb) {
 		ModelAndView mav = new ModelAndView();
-		String custNo = TscSession.getAttribute("custNo");
+		String custNo = "";
+
+		if ("find".equals(pageGb)) { //비밀번호 찾기 사용
+			custNo = TscSession.getAttribute("custNo");
+		}
+
+		if ("temp".equals(pageGb)) { // 비밀번호 변경 캠페인, 임시비밀번호로 로그인시 사용
+			custNo = String.valueOf(TsfSession.getInfo().getCustNo());
+		}
 
 		// 고객번호 없으면 인증화면으로 돌아감
 		if (StringUtils.isBlank(custNo)) {
@@ -252,7 +262,7 @@ public class TsfCustomerController extends TsfBaseController {
 		if (custInfo != null) {
 			mav.addObject("custId", custInfo.getCustId());
 		}
-
+		mav.addObject("pageGb", pageGb);
 		mav.setViewName(super.getDeviceViewName("customer/PasswordChangeForm"));
 		return mav;
 	}
@@ -269,8 +279,14 @@ public class TsfCustomerController extends TsfBaseController {
 	@ResponseBody
 	public GagaMap resetPassword(@RequestBody Customer customer) {
 		GagaMap result = new GagaMap();
-		String custNo = TscSession.getAttribute("custNo");
 		boolean isSuccess = false;
+		String custNo = "";
+		if (TsfSession.isLogin()) {
+			custNo = String.valueOf(TsfSession.getInfo().getCustNo());
+		} else {
+			custNo = TscSession.getAttribute("custNo");
+		}
+
 		if (StringUtils.isBlank(custNo)) {
 			throw new IllegalStateException("고객 정보가 없습니다. 다시 확인 해주세요.");
 		}
@@ -687,19 +703,23 @@ public class TsfCustomerController extends TsfBaseController {
 	 */
 	@PostMapping("/dormant/release")
 	@ResponseBody
-	public GagaMap releaseDormantCustomer(@RequestBody Customer customer) {
+	public GagaMap releaseDormantCustomer(@RequestBody Customer customer, HttpSession session) {
 		String custNo = TsfSession.getAttribute("custNo");
 		if (StringUtils.isBlank(custNo) || StringUtils.isBlank(customer.getEncData())) {
-			throw new IllegalStateException("로그인 후 재인증 해주세요.");
+			throw new IllegalStateException("로그인 다시 시도해주세요.");
 		}
+		GagaMap resultInfo = niceCertify.getCertifyCellPhoneResultInfo(customer);
+
+		customer.setCi(resultInfo.getString("sCi"));
 		customer.setCustNo(Integer.parseInt(custNo));
+		session.removeAttribute("custNo"); // 고객번호 세션 삭제
 		return customerService.releaseDormantCustomer(customer);
 	}
 
 	/**
 	 * 휴면해제 완료화면
 	 *
-	 * @return ModelAndView - 가입완료 화면
+	 * @return ModelAndView - 휴면해제 완료화면
 	 * @author jsshin
 	 * @since 2021. 03. 08
 	 */
@@ -712,6 +732,70 @@ public class TsfCustomerController extends TsfBaseController {
 		return mav;
 	}
 
+	/**
+	 * 본인인증 화면
+	 *
+	 * @return ModelAndView - 가입완료 화면
+	 * @author jsshin
+	 * @since 2021. 03. 10
+	 */
+	@GetMapping("/certification/form")
+	public ModelAndView getCertificationForm() {
+		ModelAndView mav = new ModelAndView();
+
+		mav.setViewName(super.getDeviceViewName("customer/CertificationForm"));
+
+		return mav;
+	}
+
+	/**
+	 * 본인인증 처리
+	 *
+	 * @param customer - 본인인증키
+	 * @return GagaMap - 결과
+	 * @author jsshin
+	 * @since 2021. 03. 11
+	 */
+	@PostMapping("/certification/save")
+	@ResponseBody
+	public GagaMap saveCertification(@RequestBody Customer customer, HttpSession session) {
+		String custNo = TsfSession.getAttribute("custNo");
+		if (StringUtils.isBlank(custNo) || StringUtils.isBlank(customer.getEncData())) {
+			throw new IllegalStateException("로그인 다시 시도해 주세요.");
+		}
+		GagaMap resultInfo = niceCertify.getCertifyCellPhoneResultInfo(customer);
+		customer.setCi(resultInfo.getString("sCi"));
+		customer.setCustNo(Integer.parseInt(custNo));
+		session.removeAttribute("custNo"); // 고객번호 세션 삭제
+		return customerService.saveCertification(customer);
+	}
+
+	/**
+	 * 비밀번호 변경 캠페인 화면
+	 *
+	 * @return ModelAndView - 가입완료 화면
+	 * @author jsshin
+	 * @since 2021. 03. 11
+	 */
+	@GetMapping("/password/campaign/form")
+	public ModelAndView getPasswordCampaignnForm() {
+		ModelAndView mav = new ModelAndView();
+
+		mav.setViewName(super.getDeviceViewName("customer/PasswordCampaignForm"));
+
+		return mav;
+	}
+
+	@PostMapping("/password/date/update")
+	@ResponseBody
+	public GagaMap updatePasswordDate(@RequestBody Customer customer) {
+		Integer custNo = TsfSession.getInfo().getCustNo();
+		if (custNo == null) {
+			throw new IllegalStateException("로그인 다시 시도해 주세요.");
+		}
+		customer.setCustNo(custNo);
+		return customerService.updatePasswordDate(customer);
+	}
 
 
 

+ 22 - 0
src/main/java/com/style24/front/support/exception/TsfNonCertificationAccountException.java

@@ -0,0 +1,22 @@
+package com.style24.front.support.exception;
+
+import org.springframework.security.core.AuthenticationException;
+
+/**
+ * 비인증 고객 로그인시 발생하는 예외
+ *
+ * @author jsshin
+ * @since 2021. 03. 10
+ */
+@SuppressWarnings("serial")
+public class TsfNonCertificationAccountException extends AuthenticationException {
+
+	public TsfNonCertificationAccountException(String msg) {
+		super(msg);
+	}
+
+	public TsfNonCertificationAccountException(String msg, Throwable t) {
+		super(msg, t);
+	}
+
+}

+ 16 - 2
src/main/java/com/style24/front/support/security/TsfAuthenticationProvider.java

@@ -3,8 +3,11 @@ package com.style24.front.support.security;
 import java.util.ArrayList;
 import java.util.List;
 
+import com.gagaframework.web.util.GagaCookieUtil;
+import com.style24.front.support.exception.TsfNonCertificationAccountException;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
 import org.springframework.security.authentication.AuthenticationProvider;
 import org.springframework.security.authentication.BadCredentialsException;
 import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
@@ -49,6 +52,11 @@ public class TsfAuthenticationProvider implements AuthenticationProvider {
 	@Autowired
 	private GagaPasswordEncoder passwordEncoder;
 
+	@Value("${has-ssl}")
+	private String hasSsl;
+
+	private static final int LOGIN_FAIL_COUNT = 5; // 실패누적건수
+
 	@Override
 	public Authentication authenticate(Authentication authentication) throws AuthenticationException {
 		String loginId = authentication.getName();
@@ -78,7 +86,7 @@ public class TsfAuthenticationProvider implements AuthenticationProvider {
 		}
 
 		// 로그인 실패누적건수가 5회 이상이면
-		if (loginInfo.getLoginFailCnt() >= 5) {
+		if (loginInfo.getLoginFailCnt() >= LOGIN_FAIL_COUNT) {
 			throw new TsfLockedAccountException(message.getMessage("LOGN_0005"));
 		}
 
@@ -93,9 +101,15 @@ public class TsfAuthenticationProvider implements AuthenticationProvider {
 			}
 		}
 
+		// 본인인증이 필요한 회원
+		if (StringUtils.isBlank(loginInfo.getCi())) {
+			TsfSession.setAttribute("custNo", String.valueOf(loginInfo.getCustNo()));
+			throw new TsfNonCertificationAccountException(message.getMessage("LOGN_0009"));
+		}
+
 		if (TscConstants.CustStat.DORMANT.value().equals(loginInfo.getCustStat())) { // 휴면회원
 
-			// 휴면해제를 위한 고객번호 세선저장
+			// 휴면해제를 위한 고객번호 세저장
 			TsfSession.setAttribute("custNo", String.valueOf(loginInfo.getCustNo()));
 			throw new TsfDormantAccountException(message.getMessage("LOGN_0006"));
 

+ 3 - 0
src/main/java/com/style24/front/support/security/handler/TsfLoginFailureHandler.java

@@ -6,6 +6,7 @@ import javax.servlet.ServletException;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
+import com.style24.front.support.exception.TsfNonCertificationAccountException;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.core.AuthenticationException;
 import org.springframework.security.web.authentication.AuthenticationFailureHandler;
@@ -57,6 +58,8 @@ public class TsfLoginFailureHandler implements AuthenticationFailureHandler {
 			result.setString("status", "SESSION_EXPIRED");
 		} else if (exception instanceof TsfEmailDuplicationException) { // SNS용 이메일 중복 시
 			result.setString("status", "EMAIL_DUP");
+		} else if (exception instanceof TsfNonCertificationAccountException){ //본인인증 필요한 회원
+			result.setString("status","CI_EMPTY");
 		} else {
 			result.setString("status", "ETC_ERROR");
 		}

+ 16 - 1
src/main/java/com/style24/front/support/security/handler/TsfLoginSuccessHandler.java

@@ -45,8 +45,12 @@ public class TsfLoginSuccessHandler implements AuthenticationSuccessHandler {
 		"/customer/pwd/find/form",					// 비밀번호찾기
 		"/customer/join/complete/form",				// 회원가입완료
 		"/customer/join/type/form",					// 회원가입유형
-		"/customer/dormant/certify/complete/form"	// 휴면해제
+		"/customer/dormant/certify/complete/form",	// 휴면해제
+		"/customer/certification/form"				// 본인인증화면
 	};
+	private static final int CHANG_PWD_CAMPAIGN_DAY = 90; // 비밀번호 변경 캠페인일자
+
+	private static final String CHANG_TEMP_PWD = "Y";	//임시비밀번호여부
 
 	@Autowired
 	private TsfLoginService loginService;
@@ -112,6 +116,17 @@ public class TsfLoginSuccessHandler implements AuthenticationSuccessHandler {
 		// 로그인 후 장바구니 Update
 		cartService.updateCartToAfterLogin(custNo);
 
+		// 비밀번호 변경 캠페인 일자
+		if (loginDetails.getLoginInfo().getPwdChgDay() >= CHANG_PWD_CAMPAIGN_DAY) {
+			returnUrl ="/customer/password/campaign/form";
+		}
+
+		// 임시비밀번호로 로그인 한 경우
+		if (CHANG_TEMP_PWD.equals(loginDetails.getLoginInfo().getTempPasswdYn())) {
+			returnUrl ="/customer/password/change/form?pageGb=temp";
+		}
+
+
 		GagaMap result = new GagaMap();
 		result.setString("status", "OK");
 		result.setString("returnUrl", returnUrl);

+ 4 - 1
src/main/java/com/style24/persistence/domain/Login.java

@@ -9,7 +9,7 @@ import lombok.Data;
 
 /**
  * 고객 Domain
- * 		@JsonSerialize 애노테이션을 지정해야 세션을 레디스에 저장할 수 있다.
+ * @JsonSerialize 애노테이션을 지정해야 세션을 레디스에 저장할 수 있다.
  * @author gagamel
  * @since 2019. 12. 4
  */
@@ -43,6 +43,9 @@ public class Login extends TscBaseDomain {
 	private String loginLdt;		// 최종로그인일시
 	private String loginFailYn;		// 로그인실패여부
 	private String custGrade;		// 고객등급
+	private String tempPasswdYn;	// 임시비밀번호여부
+	private int pwdChgDay;			// 비밀번호변경일자
+	private String ci;				// CI(본인인증여부)
 
 	// 암호화 대상 복호화 처리 =================================================
 	public String getCustNm() {

+ 44 - 24
src/main/java/com/style24/persistence/mybatis/shop/TsfCustomer.xml

@@ -445,28 +445,27 @@
 	<!-- 위시리스트 등록 -->
 	<insert id="createWishList" parameterType="WishList">
 		/* TsfCustomer.createWishList */
-		INSERT INTO TB_WISHLIST
-		(
-		            CUST_NO
-		          , GOODS_CD
-		          , AF_LINK_CD
-		          , ITHR_CD
-		          , CONTENTS_LOC
-		          , PLAN_DTL_SQ
-		          , REG_NO
-		          , REG_DT
-		         ) VALUES (
-		            #{custNo}
-		          , #{goodsCd}
-		          , #{afLinkCd}
-		          , #{ithrCd}
-		          , #{contentsLoc}
-		          , #{planDtlSq}
-		          , #{regNo}
-		          , NOW()
-		         )
+		INSERT INTO TB_WISHLIST (
+		       CUST_NO
+		     , GOODS_CD
+		     , AF_LINK_CD
+		     , ITHR_CD
+		     , CONTENTS_LOC
+		     , PLAN_DTL_SQ
+		     , REG_NO
+		     , REG_DT
+		) VALUES (
+		       #{custNo}
+		     , #{goodsCd}
+		     , #{afLinkCd}
+		     , #{ithrCd}
+		     , #{contentsLoc}
+		     , #{planDtlSq}
+		     , #{regNo}
+		     , NOW()
+		)
 		ON DUPLICATE KEY UPDATE
-		         REG_DT = NOW()
+		       REG_DT = NOW()
 	</insert>
 
 	<!-- 위시리스트 삭제 -->
@@ -480,18 +479,18 @@
 		    <foreach collection="arrGoodsCd" item="item" index="index"  open="(" close=")" separator=",">
 		UPPER(#{item})
 		    </foreach>
-		</when>	
+		</when>
 		<otherwise>
 		AND    GOODS_CD = #{goodsCd}
 		</otherwise>
 		</choose>
 	</delete>
-	
+
 	<!-- 위시리스트 삭제 상품 조회 -->
 	<select id="getDeleteGoodsWish" parameterType="int" resultType="String">
 		/* TsfCustomer.getDeleteGoodsWish */
 		SELECT GROUP_CONCAT(GOODS_CD) AS GOODS_CD
-		FROM ( 
+		FROM (
 		      SELECT GOODS_CD , REG_DT
 		           , RANK() OVER(ORDER BY REG_DT DESC) AS RNUM
 		      FROM TB_WISHLIST
@@ -500,4 +499,25 @@
 		WHERE RNUM > 50
 	</select>
 
+
+	<!--본인인증처리-->
+	<update id="updateCustomerCi" parameterType="Customer">
+		/* TsfCustomer.updateCustomerCi */
+		UPDATE TB_CUSTOMER
+		SET    CI = #{ci}
+		     , AUTH_DT = NOW()
+		     , UPD_NO = #{updNo}
+		     , UPD_DT = NOW()
+		WHERE  CUST_NO = #{custNo}
+	</update>
+
+	<!--비밀번호 변경 날짜 업데이트-->
+	<update id="updatePasswordDate" parameterType="Customer">
+		UPDATE TB_CUSTOMER
+		SET    PASSWD_CHG_DT = DATE_ADD(NOW(), INTERVAL -#{pwdChangeDay} DAY )
+		     , UPD_NO = #{updNo}
+		     , UPD_DT = NOW()
+		WHERE  CUST_NO = #{custNo}
+	</update>
+
 </mapper>

+ 20 - 17
src/main/java/com/style24/persistence/mybatis/shop/TsfLogin.xml

@@ -5,33 +5,36 @@
 	<!-- 로그인체크 정보 조회 -->
 	<select id="getLoginCheckInfo" parameterType="Login" resultType="Login">
 		/* TsfLogin.getLoginCheckInfo */
-		SELECT CUST_NO                                          /*고객번호*/
-		     , CUST_ID                                          /*고객ID*/
-		     , CUST_NM                                          /*고객명*/
-		     , PASSWD                                           /*비밀번호*/
-		     , CUST_GB                                          /*고객구분*/
-		     , FN_GET_CODE_NM('G100',CUST_GB) AS CUST_GB_NM     /*고객구분명*/
-		     , CUST_STAT                                        /*회원상태*/
-		     , CELL_PHNNO                                       /*휴대전화번호*/
-		     , EMAIL                                            /*이메일*/
-		     , #{snsType}                     AS SNS_TYPE       /*SNS유형*/
-		     , #{snsId}                       AS SNS_ID         /*SNS가입ID*/
+		SELECT CUST_NO                                                 /*고객번호*/
+		     , CUST_ID                                                 /*고객ID*/
+		     , CUST_NM                                                 /*고객명*/
+		     , PASSWD                                                  /*비밀번호*/
+		     , CUST_GB                                                 /*고객구분*/
+		     , FN_GET_CODE_NM('G100',CUST_GB) AS CUST_GB_NM            /*고객구분명*/
+		     , CUST_STAT                                               /*회원상태*/
+		     , CELL_PHNNO                                              /*휴대전화번호*/
+		     , EMAIL                                                   /*이메일*/
+		     , #{snsType}                     AS SNS_TYPE              /*SNS유형*/
+		     , #{snsId}                       AS SNS_ID                /*SNS가입ID*/
 		     , IFNULL((SELECT LOGIN_FAIL_CNT
 		               FROM   TB_LOGIN_FAIL
 		               WHERE  CUST_ID = #{custId}
 		               AND    IP_ADDR = #{ipAddr}
 		               AND    SITE_CD = #{siteCd}
-		              ),0)                    AS LOGIN_FAIL_CNT /*로그인실패건수*/
+		              ),0)                    AS LOGIN_FAIL_CNT         /*로그인실패건수*/
+		     , TEMP_PASSWD_YN                                           /*임시비밀번호여부*/
+		     , IFNULL(DATEDIFF(NOW(), PASSWD_CHG_DT), 0) AS PWD_CHG_DAY /*비밀번호변경일자*/
+		     , CI                                                       /*CI본인인증여부*/
 		FROM   TB_CUSTOMER A
 		WHERE  1 = 1
 		<choose>
 		    <when test="snsType != null and snsType != ''"> <!-- SNS 로그인  -->
 		AND    CUST_NO = (
-		               SELECT CUST_NO
-		               FROM TB_CUSTOMER_SNS
-		               WHERE SNS_TYPE = #{snsType}
-		               AND   SNS_ID = #{snsId}
-		               )
+		                  SELECT CUST_NO
+		                  FROM   TB_CUSTOMER_SNS
+		                  WHERE  SNS_TYPE = #{snsType}
+		                  AND    SNS_ID = #{snsId}
+		                 )
 		    </when>
 		    <when test="custNo != null and custNo != ''">
 		AND    CUST_NO = #{custNo}

+ 2 - 0
src/main/resources/i18n/messages/message_ko_KR.properties

@@ -32,6 +32,8 @@ LOGN_0005=\uBE44\uBC00\uBC88\uD638\uAC00 5\uD68C \uC774\uC0C1 \uD2C0\uB824 \uACC
 LOGN_0006=\uD734\uBA74 \uD68C\uC6D0\uC785\uB2C8\uB2E4.
 LOGN_0007=\uD0C8\uD1F4 \uD68C\uC6D0\uC785\uB2C8\uB2E4.
 LOGN_0008=\uC774\uBBF8 \uAC00\uC785\uD558\uC2E0 \uC774\uBA54\uC77C\uC774 \uC874\uC7AC\uD569\uB2C8\uB2E4.
+LOGN_0009=\uBCF8\uC778\uC778\uC99D\uC774 \uD544\uC694\uD55C \uD68C\uC6D0\uC785\uB2C8\uB2E4.
+
 
 ##\uC7A5\uBC14\uAD6C\uB2C8
 CART_0001=\uC7A5\uBC14\uAD6C\uB2C8\uC5D0 \uB2F4\uACBC\uC2B5\uB2C8\uB2E4.

+ 9 - 1
src/main/webapp/WEB-INF/views/web/SigninFormWeb.html

@@ -163,12 +163,20 @@
 								cfnGoToPage(_PAGE_CUSTOMER_DORMANT);
 							}
 						});
-
 						return;
 					} else if (result.status == 'SECEDE_CUST') {
 						// 탈퇴회원
 					} else if (result.status == 'SESSION_EXPIRED') {
 						// 세션만료
+					} else if (result.status == 'CI_EMPTY') {
+						// 본인이증 필요한 회원
+						mcxDialog.alertC("본인인증 후 다시 로그인 하시기 바랍니다.", {
+							sureBtnText: "확인",
+							sureBtnClick: function() {
+								cfnGoToPage(_PAGE_CUSTOMER_CERTIFICATION);
+							}
+						});
+						return;
 					}
 
 					if (!gagajf.isNull(result.message)) {

+ 80 - 0
src/main/webapp/WEB-INF/views/web/customer/CertificationFormWeb.html

@@ -0,0 +1,80 @@
+<!DOCTYPE html>
+<html lang="ko"
+	xmlns:th="http://www.thymeleaf.org"
+	xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
+	layout:decorator="web/common/layout/DefaultLayoutWeb">
+<!--
+ *******************************************************************************
+ * @source  : DormantCertifyFormWeb.html
+ * @desc    : 휴면회원 본인인증 Page
+ *============================================================================
+ * STYLE24
+ * Copyright(C) 2021 TSIT, All rights reserved.
+ *============================================================================
+ * VER  DATE         AUTHOR      DESCRIPTION
+ * ===  ===========  ==========  =============================================
+ * 1.0  2021.02.05   jsshin     최초 작성
+ *******************************************************************************
+ -->
+<body>
+
+<th:block layout:fragment="content">
+<div id="container" class="container mb">
+	<div class="wrap">
+		<div class="content dormant"> <!-- 페이지특정 클래스 = dormant -->
+			<div class="cont_head">
+				<h4>본인인증</h4>
+			</div>
+			<div class="cont_body">
+				<form class="form_wrap form_col_c form_full" role="form">
+					<div class="form_info">
+						<span class="ico_content_dormant"></span>
+						<p class="c_primary">본인인증이 필요한 고객이므로 본인인증 해주시기 바랍니다.</p>
+					</div>
+					<div class="btn_group_block">
+						<div class="ui_row">
+							<div class="ui_col_12">
+								<button type="button" class="btn btn_default btn_block" onclick="cfnOpenCellphoneCertify();">
+									<span><i class="ico ico_phone"></i>휴대폰인증</span>
+								</button>
+							</div>
+						</div>
+					</div>
+				</form>
+			</div>
+		</div>
+	</div>
+</div>
+
+<script th:inline="javascript">
+/*<![CDATA[*/
+	// 나이스 본인인증 후 콜백
+	var fnNiceCallBack = function(encData) {
+		if (!gagajf.isNull(encData)) {
+			let custInfo = {};
+			custInfo.encData = encData;
+			let jsonData = JSON.stringify(custInfo);
+			gagajf.ajaxJsonSubmit('/customer/certification/save', jsonData, fnCertificationCallback);
+		}
+	};
+
+	var fnCertificationCallback = function (result) {
+		if (result.isSuccess) { //인증 성공시 다시 로그인 페이지
+			mcxDialog.alertC("본인인증 완료 되었습니다.", {
+				sureBtnText: "확인",
+				sureBtnClick: function() {
+					cfnGoToPage(_PAGE_MAIN);
+				}
+			});
+			return;
+		} else { // 이미 가입된 이력이 있는 경우 완료 페이지
+			cfnGoToPage(_PAGE_CUSTOMER_JOIN_COMPLETE);
+		}
+	}
+/*]]>*/
+</script>
+
+</th:block>
+
+</body>
+</html>

+ 5 - 1
src/main/webapp/WEB-INF/views/web/customer/DormantCertifyFormWeb.html

@@ -74,7 +74,11 @@
 		if (result.isRelase) {
 			cfnGoToPage(_PAGE_CUSTOMER_DORMANT_COMPLETE);
 		} else {
-			mcxDialog.alert("휴면해제 실패하였습니다. <br> 고객센터에 문의 하시기 바랍니다.");
+			let msg = "휴면 해제 실패하였습니다. <br> 고객센터에 문의하시기 바랍니다.";
+			if (result.errorType === 'DIFFERENT_CI') {
+				msg = "등록된 본인인증 정보와 다릅니다. <br> 고객센터에 문의하시기 바랍니다.";
+			}
+			mcxDialog.alert(msg);
 			return;
 		}
 	}

+ 80 - 0
src/main/webapp/WEB-INF/views/web/customer/PasswordCampaignFormWeb.html

@@ -0,0 +1,80 @@
+<!DOCTYPE html>
+<html lang="ko"
+	xmlns:th="http://www.thymeleaf.org"
+	xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
+	layout:decorator="web/common/layout/DefaultLayoutWeb">
+<!--
+ *******************************************************************************
+ * @source  : PasswordCampaignFormWeb.html
+ * @desc    : 비밀번호 캠페인 화면 Page
+ *============================================================================
+ * STYLE24
+ * Copyright(C) 2021 TSIT, All rights reserved.
+ *============================================================================
+ * VER  DATE         AUTHOR      DESCRIPTION
+ * ===  ===========  ==========  =============================================
+ * 1.0  2021.03.11   jsshin     최초 작성
+ *******************************************************************************
+ -->
+<body>
+
+<th:block layout:fragment="content">
+<div id="container" class="container mb">
+	<div class="wrap">
+		<div class="content campaign"> <!-- 페이지특정 클래스 = campaign -->
+			<div class="cont_head">
+				<h4>비밀번호 변경 캠페인</h4>
+			</div>
+			<div class="cont_body">
+				<form class="form_wrap form_col_c" role="form">
+					<div class="form_info">
+						<span class="ico_content_security"></span>
+						<p class="">고객님! <span class="c_primary">비밀번호 변경</span>으로 <br>소중한 개인정보를 지켜주세요!</p>
+						<p class="c_primary mt5">고객님은 3개월동안 비밀번호를 변경하지 않으셨습니다!</p>
+					</div>
+					<div class="form_summary t_c">
+						<p class="t_info mt10">장기간 비밀번호를 변경하지 않고 동일한 비밀번호를 사용중인 경우,
+							<br> 개인정보를 안전하게 보호하고, 개인정보 도용으로 인한 피해를 방지하기 위해
+							<br>주기적으로 비밀번호를 변경하도록 안내해드리고 있습니다.
+						</p>
+						<p class="t_info mt10">고객님의 소중한 정보 보호를 위해 적극적인 참여 부탁 드립니다.</p>
+					</div>
+					<div class="btn_group_block btn_group_md ui_row">
+						<div class="ui_col_6">
+							<button type="button" class="btn btn_primary btn_block" onclick="cfnGoToPage(_PAGE_CUSTOMER_PWD_CHANGE_TEMP)">
+								<span>변경하기</span>
+							</button>
+						</div>
+						<div class="ui_col_6">
+							<button type="button" class="btn btn_dark btn_block" id="btnPwdNext">
+								<span>30일간 보지않기</span>
+							</button>
+						</div>
+					</div>
+				</form>
+			</div>
+		</div>
+	</div>
+</div>
+
+
+<script th:inline="javascript">
+/*<![CDATA[*/
+
+	// 30일간 보지 않기
+	$('#btnPwdNext').on('click', function () {
+		let jsonData = JSON.stringify({});
+		gagajf.ajaxJsonSubmit('/customer/password/date/update', jsonData, fnPwdDateUpdateCallback);
+	});
+
+	var fnPwdDateUpdateCallback = function (result) {
+		cfnGoToPage(_PAGE_MAIN);
+	}
+
+/*]]>*/
+</script>
+
+</th:block>
+
+</body>
+</html>

+ 10 - 3
src/main/webapp/WEB-INF/views/web/customer/PasswordChangeFormWeb.html

@@ -23,7 +23,8 @@
 	<div class="wrap">
 		<div class="content find">
 			<div class="cont_head">
-				<h4>아이디&#47;비밀번호 찾기</h4>
+				<h4 th:if="${pageGb == 'find'}">아이디&#47;비밀번호 찾기</h4>
+				<h4 th:if="${pageGb == 'temp'}">비밀번호 변경</h4>
 			</div>
 			<div class="cont_body show">
 				<form id="resetPasswordForm" name="resetPasswordForm" class="form_wrap form_col_c" role="form" method="post">
@@ -89,7 +90,8 @@
 						<div class="btn_group_block btn_group_md ui_row">
 							<div class="ui_col_12">
 								<button type="button" id="btnSavePassword" class="btn btn_dark btn_block" disabled="disabled">
-									<span>변경 후 다시 로그인</span>
+									<span th:if="${pageGb == 'find'}">변경 후 다시 로그인</span>
+									<span th:if="${pageGb == 'temp'}">변경하기</span>
 								</button>
 							</div>
 						</div>
@@ -104,6 +106,7 @@
 <script th:src="@{'/biz/customer.js?v=' + ${#calendars.format(#calendars.createNow(), 'yyyyMMddHHmmss')}}" src="/biz/customer.js"></script>
 <script th:inline="javascript">
 /*<![CDATA[*/
+	const pageGb = [[${pageGb}]];
 
 	// 비밀번호 입력
 	$('#resetPasswordForm input[name=passwd]').on('focusout keyup keydown', function () {
@@ -226,7 +229,11 @@
 		mcxDialog.alertC('비밀번호 변경이 완료 되었습니다.', {
 			sureBtnText: "확인",
 			sureBtnClick: function() {
-				cfnGoToPage(_PAGE_LOGIN);
+				if (pageGb === 'find') {
+					cfnGoToPage(_PAGE_LOGIN);
+				} else if (pageGb === 'temp') {
+					cfnGoToPage(_PAGE_MAIN);
+				}
 			}
 		});
 		} else {

+ 1 - 0
src/main/webapp/ux/style24_link.js

@@ -18,6 +18,7 @@ const _PAGE_CUSTOMER_PWD_CHANGE_FIND = _frontUrl + "/customer/password/change/fo
 const _PAGE_CUSTOMER_PWD_CHANGE_TEMP = _frontUrl + "/customer/password/change/form?pageGb=temp";	// 고객 > 임시비밀번호 로그인 > 비밀번호 변경 화면
 const _PAGE_CUSTOMER_DORMANT = _frontUrl + "/customer/dormant/certify/form";						// 고객 > 휴면회원
 const _PAGE_CUSTOMER_DORMANT_COMPLETE = _frontUrl + "/customer/dormant/certify/complete/form";		// 고객 > 휴면회원 > 완료페이지
+const _PAGE_CUSTOMER_CERTIFICATION = "/customer/certification/form"									// 고객 > 본인인증화면
 
 //== 상품상세 ==/
 const _PAGE_GOODS_DETAIL = _frontUrl + "/goods/detail/form?goodsCd=";								// 상품 상세