비밀번호 처리 기능 보완
This commit is contained in:
parent
7ccba8a51f
commit
c34019243d
@ -6,7 +6,7 @@
|
||||
<articleType>101</articleType>
|
||||
<articleTypeName>Q&A</articleTypeName>
|
||||
<title>공지사항 테스트</title>
|
||||
<articlePassword>111</articlePassword>
|
||||
<articlePassword>9uCh4qxBlFqap/+KiqoM68EqO8yYGpKa1c+BCgkOEa4=</articlePassword><!-- 111 -->
|
||||
<readCount>15</readCount>
|
||||
<regDate>2021-07-19</regDate>
|
||||
<regUserName>김아무</regUserName>
|
||||
|
||||
@ -23,6 +23,7 @@ import nlib.bbs.service.BoardService;
|
||||
import nlib.cmm.NlibCommonController;
|
||||
import nlib.cmm.crypto.AriaCrypto;
|
||||
import nlib.cmm.crypto.NlibPasswordEncoder;
|
||||
import nlib.cmm.exception.ErrorMessage;
|
||||
import nlib.cmm.service.CodeService;
|
||||
import nlib.cmm.service.NlibProperty;
|
||||
import nlib.restful.service.DataApiReqVO;
|
||||
@ -180,7 +181,6 @@ public class BoardController extends NlibCommonController
|
||||
String pageSize = paramMap.get("pageSize");
|
||||
String message = paramMap.get("message");
|
||||
|
||||
|
||||
// 게시물 번호
|
||||
String articleNo = paramMap.get("articleNo");
|
||||
|
||||
@ -197,24 +197,19 @@ public class BoardController extends NlibCommonController
|
||||
reqVO.setAuthKey(createAuthKey(req, authentication));
|
||||
reqVO.setPageIndex(pageIndex);
|
||||
reqVO.setPageSize(pageSize);
|
||||
|
||||
// 추가 정보 설정 : 게시판ID, 게시물번호
|
||||
HashMap<String, Object> info = new HashMap<String, Object>();
|
||||
info.put("boardNo", "QNA");
|
||||
info.put("articleNo", articleNo);
|
||||
reqVO.setInfo(info);
|
||||
reqVO.addInfoItem("boardNo", "QNA"); // 게시판ID
|
||||
reqVO.addInfoItem("articleNo", articleNo); // 게시물번호
|
||||
|
||||
// 요청
|
||||
DataApiResVO resVO = boardService.selectQnA(reqVO);
|
||||
|
||||
// 반환 정보
|
||||
model.addAttribute("articleNo" , articleNo);
|
||||
model.addAttribute("article" , resVO.getInfo());
|
||||
model.addAttribute("preArticle" , resVO.getList().get(0));
|
||||
model.addAttribute("nextArticle" , resVO.getList().get(1));
|
||||
model.addAttribute("article" , resVO.getInfo()); // 게시물 상세
|
||||
model.addAttribute("preArticle" , resVO.getList().get(0)); // 이전글 정보
|
||||
model.addAttribute("nextArticle" , resVO.getList().get(1)); // 다음글 정보
|
||||
model.addAttribute("message" , message);
|
||||
|
||||
model.addAttribute("pageIndex" , pageIndex);
|
||||
model.addAttribute("pageIndex" , pageIndex);
|
||||
model.addAttribute("pageSize" , pageSize);
|
||||
model.addAttribute("searchKeyword", searchKeyword);
|
||||
|
||||
@ -305,20 +300,19 @@ public class BoardController extends NlibCommonController
|
||||
reqVO.setAuthKey(createAuthKey(req, authentication));
|
||||
reqVO.setPageIndex(pageIndex);
|
||||
reqVO.setPageSize(pageSize);
|
||||
|
||||
// 추가 정보 설정 : 게시판ID, 게시물번호
|
||||
HashMap<String, Object> info = new HashMap<String, Object>();
|
||||
info.put("boardNo", "QNA");
|
||||
info.put("articleNo", articleNo);
|
||||
reqVO.setInfo(info);
|
||||
reqVO.addInfoItem("boardNo", "QNA"); // 게시판ID
|
||||
reqVO.addInfoItem("articleNo", articleNo); // 게시물번호
|
||||
|
||||
// 요청
|
||||
DataApiResVO resVO = boardService.selectQnA(reqVO);
|
||||
|
||||
// 비밀번호 확인
|
||||
HashMap<String, Object> article = resVO.getInfo();
|
||||
if(!articlePassword.equals(article.get("articlePassword"))) {
|
||||
model.addAttribute("message", "비밀빈호가 올바르지 않습니다.(1)");
|
||||
String shaArticlePassword = nlibPasswordEncoder.encode(articlePassword);
|
||||
log.debug("updateQnAForm > 입력받은 비밀번호를 SHA256 암호화한 값 : " + shaArticlePassword);
|
||||
|
||||
if(!shaArticlePassword.equals(article.get("articlePassword"))) {
|
||||
model.addAttribute("message", "비밀번호가 올바르지 않습니다.(1)");
|
||||
return "redirect:/board/selectQnA.do";
|
||||
}
|
||||
|
||||
@ -326,13 +320,16 @@ public class BoardController extends NlibCommonController
|
||||
model.addAttribute("articleNo" , articleNo);
|
||||
model.addAttribute("article" , resVO.getInfo());
|
||||
|
||||
//-------------------------------
|
||||
// 게시글 비밀번호 처리
|
||||
String shaArticlePassword = nlibPasswordEncoder.encode(articlePassword);
|
||||
String encArticlePassword = ariaCrypto.encode(shaArticlePassword, createAuthKey(req, authentication));
|
||||
//-------------------------------
|
||||
// 비밀번호 : SHA-256 암호화 처리되어 DB에 저장되며,
|
||||
// 웹 화면에 표출될 때는 Aria로 articleNo를 Salt값으로 하여 재암호화처리하고 BASE64로 다시 한번 인코딩하여 표출함
|
||||
String encArticlePassword = StringUtil.encodeBase64(ariaCrypto.encode(shaArticlePassword, articleNo));
|
||||
model.addAttribute("encArticlePassword", encArticlePassword);
|
||||
|
||||
// 검색 정보
|
||||
model.addAttribute("pageIndex" , pageIndex);
|
||||
model.addAttribute("pageIndex" , pageIndex);
|
||||
model.addAttribute("pageSize" , pageSize);
|
||||
model.addAttribute("searchKeyword", searchKeyword);
|
||||
|
||||
@ -354,8 +351,15 @@ public class BoardController extends NlibCommonController
|
||||
|
||||
// 게시물 번호
|
||||
String articleNo = paramMap.get("articleNo");
|
||||
|
||||
//-------------------------------
|
||||
// 게시글 비밀번호 처리
|
||||
//-------------------------------
|
||||
// 비밀번호 : SHA-256 암호화 처리되어 DB에 저장되며,
|
||||
// 웹 화면에 표출될 때는 Aria로 articleNo를 Salt값으로 하여 재암호화처리하고 BASE64로 다시 한번 인코딩하여 표출함
|
||||
String encArticlePassword = paramMap.get("encArticlePassword");
|
||||
String checkArticlePassword = ariaCrypto.decode(encArticlePassword, authKey);
|
||||
String checkArticlePassword = ariaCrypto.decode(StringUtil.decodeBase64(encArticlePassword), articleNo);
|
||||
String articlePassword = paramMap.get("articlePassword");
|
||||
|
||||
//-------------------------------
|
||||
// 비밀번호 유효 체크
|
||||
@ -368,11 +372,20 @@ public class BoardController extends NlibCommonController
|
||||
DataApiResVO resVO = boardService.selectQnA(reqVO);
|
||||
String oldArticlePassword = resVO.getInfoItem("articlePassword");
|
||||
if(checkArticlePassword == null || !checkArticlePassword.equals(oldArticlePassword)) {
|
||||
message = "잘못된 접근입니다.";
|
||||
// TODO 수정화면으로 다시 redirect 시킬것
|
||||
return "redirect:/board/updateQnAForm.do";
|
||||
model.addAttribute("errorMessage", new ErrorMessage("ERR_BRD_UPDTQNA", "잘못된 접근입니다."));
|
||||
return "redirect:/alert/showError.do";
|
||||
}
|
||||
|
||||
|
||||
// 새 글비밀번호가 존재하지 않는 경우, 기존 비밀번호 설정 처리
|
||||
if(StringUtil.isEmpty(articlePassword)) {
|
||||
articlePassword = checkArticlePassword;
|
||||
}
|
||||
// 새 글비밀번호가 입력된 경우, SHA256 암호화 처리하여 설정
|
||||
else {
|
||||
articlePassword = nlibPasswordEncoder.encode(articlePassword);
|
||||
}
|
||||
|
||||
//-------------------------------
|
||||
// REQ VO 구성
|
||||
//-------------------------------
|
||||
@ -384,6 +397,7 @@ public class BoardController extends NlibCommonController
|
||||
updateReqVO.addInfoItem("regUserName" , paramMap.get("regUserName"));
|
||||
updateReqVO.addInfoItem("email" , paramMap.get("email"));
|
||||
updateReqVO.addInfoItem("contentQeust", paramMap.get("contentQeust"));
|
||||
updateReqVO.addInfoItem("articlePassword", articlePassword); // SHA256 글비밀번호
|
||||
|
||||
// 요청
|
||||
DataApiResVO updateResVO = boardService.updateQnA(updateReqVO);
|
||||
@ -391,18 +405,19 @@ public class BoardController extends NlibCommonController
|
||||
// 처리결과 확인
|
||||
if(!updateResVO.isSuccess()) {
|
||||
message = updateResVO.getResultMessage();
|
||||
addParamsToModel(paramMap, model);
|
||||
return "redirect:/board/updateQnAForm.do";
|
||||
}
|
||||
|
||||
// 반환 정보
|
||||
model.addAttribute("articleNo" , updateResVO.getInfoItem("articleNo")); // 신규등록된 게시물 ID
|
||||
model.addAttribute("article" , resVO.getInfo());
|
||||
model.addAttribute("message" , "성공적으로 수정처리되었습니다.");
|
||||
|
||||
// 검색 정보
|
||||
model.addAttribute("pageIndex" , pageIndex);
|
||||
model.addAttribute("pageSize" , pageSize);
|
||||
model.addAttribute("searchKeyword", searchKeyword);
|
||||
model.addAttribute("message" , "");
|
||||
|
||||
return "redirect:nlib/board/selectQnA";
|
||||
}
|
||||
@ -412,5 +427,4 @@ public class BoardController extends NlibCommonController
|
||||
return "nlib/board/deleteQnA";
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -3,6 +3,7 @@ package nlib.cmm;
|
||||
import java.util.Base64;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
@ -12,6 +13,7 @@ import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.ui.ModelMap;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
@ -21,6 +23,7 @@ import nlib.cmm.exception.ErrorMessage;
|
||||
import nlib.restful.service.DataApiResVO;
|
||||
import nlib.security.SecUserVO;
|
||||
import nlib.user.service.NlibLoginVO;
|
||||
import nlib.util.StringUtil;
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
@ -175,4 +178,21 @@ public class NlibCommonController {
|
||||
return ResponseEntity.ok().headers(headers).body(jsonStr);
|
||||
}
|
||||
|
||||
public ModelMap addParamsToModel(Map<String, String> paramMap, ModelMap model) {
|
||||
return addParamsToModel(paramMap, model, null, null);
|
||||
}
|
||||
public ModelMap addParamsToModel(Map<String, String> paramMap, ModelMap model, String upperMapName, String itemNames) {
|
||||
|
||||
if(paramMap == null || paramMap.size() < 1) return model;
|
||||
if(model == null) return model;
|
||||
|
||||
boolean existUpperMap = StringUtil.isNotEmpty(upperMapName);
|
||||
Map<String, String> uppperMap = new HashMap<String, String>();
|
||||
for(String key : paramMap.keySet()) {
|
||||
model.addAttribute(key, paramMap.get(key));
|
||||
}
|
||||
|
||||
return model;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -14,4 +14,20 @@ public class ErrorMessage {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
public String getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public void setCode(String code) {
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
public void setMessage(String message) {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
55
src/main/java/nlib/cmm/web/AlertController.java
Normal file
55
src/main/java/nlib/cmm/web/AlertController.java
Normal file
@ -0,0 +1,55 @@
|
||||
package nlib.cmm.web;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.ModelMap;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
|
||||
import nlib.cmm.exception.ErrorMessage;
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* @Class Name : AlertController.java
|
||||
*
|
||||
* @Description : 각종 처리 결과/오류 안내관련 공통 컨트롤러 클래스
|
||||
*
|
||||
*
|
||||
* @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @ ------------ -------- ---------------------------
|
||||
* @ 수정일 수정자 수정내용
|
||||
* @ ------------ -------- ---------------------------
|
||||
* @ 2021. 7. 29. KNKIM 최초 생성
|
||||
*
|
||||
*
|
||||
* @author 이씨플라자 * DIGITALSHIP KNKIM
|
||||
* @since 2021. 7. 29.
|
||||
* @version 1.0
|
||||
*
|
||||
*/
|
||||
@Controller
|
||||
public class AlertController {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(SystemController.class);
|
||||
|
||||
/**
|
||||
* NLIB Property 재로드 작업을 요청한다.
|
||||
*
|
||||
* @param authentication
|
||||
* @param model
|
||||
* @return
|
||||
*/
|
||||
@RequestMapping( {"/alert/showError.do"} )
|
||||
public String showError(@RequestParam ErrorMessage errorMessage, ModelMap model) {
|
||||
|
||||
model.addAttribute("code", errorMessage.getCode());
|
||||
model.addAttribute("message", errorMessage.getMessage());
|
||||
|
||||
return "nlib/cmm/common";
|
||||
}
|
||||
|
||||
}
|
||||
@ -2,6 +2,9 @@ package nlib.util;
|
||||
|
||||
import java.sql.Timestamp;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Base64;
|
||||
import java.util.Base64.Decoder;
|
||||
import java.util.Base64.Encoder;
|
||||
import java.util.Locale;
|
||||
|
||||
import egovframework.com.utl.fcc.service.EgovStringUtil;
|
||||
@ -107,4 +110,31 @@ public class StringUtil extends EgovStringUtil {
|
||||
|
||||
return rtnStr;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Base64로 인코딩한다.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static String encodeBase64(String str) {
|
||||
|
||||
if(str == null) return null;
|
||||
|
||||
Encoder encoder = Base64.getEncoder();
|
||||
return new String(encoder.encode(str.getBytes()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Base64로 디코딩한다.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static String decodeBase64(String str) {
|
||||
|
||||
if(str == null) return null;
|
||||
|
||||
Decoder decoder = Base64.getDecoder();
|
||||
return new String(decoder.decode(str.getBytes()));
|
||||
}
|
||||
}
|
||||
|
||||
@ -38,12 +38,7 @@
|
||||
<head>
|
||||
<title>${pageTitle}</title>
|
||||
|
||||
<!-- GRID -->
|
||||
<link type="text/css" rel="stylesheet" href="/nlib/js/jsgrid/nlib-jsgrid.css" />
|
||||
<link type="text/css" rel="stylesheet" href="/nlib/js/jsgrid/nlib-jsgrid-theme.css" />
|
||||
<script src="/nlib/js/jsgrid/nlib-jsgrid.js"></script>
|
||||
|
||||
<script type="text/javaScript" language="javascript">
|
||||
<script type="text/javaScript">
|
||||
|
||||
//선택한 게시글 상세 보기로 이동
|
||||
function fn_viewDetail(articleNo) {
|
||||
@ -58,24 +53,18 @@ function fn_list() {
|
||||
$("#articleForm").submit();
|
||||
}
|
||||
|
||||
|
||||
var fn_updateForm = function (passwd) {
|
||||
if(passwd == null || passwd == "") {
|
||||
alert("수정을 위한 게시물의 비밀번호를 입력하여 주시기 바랍니다.");
|
||||
return;
|
||||
}
|
||||
|
||||
$("#articlePassword").val(passwd);
|
||||
$("#articleForm").attr("action", "${pageContext.request.contextPath}/board/updateQnAForm.do");
|
||||
$("#articleForm").submit();
|
||||
}
|
||||
|
||||
// 수정 처리
|
||||
function fn_update() {
|
||||
if(!confirm("저장하시겠습니까?")) return;
|
||||
if(!validEmail($("#email").val())) {
|
||||
alert("이메일 형식에 맞지 않습니다. 다시 확인하여 주시기 바랍니다.");
|
||||
$("#email").focus();
|
||||
return false;
|
||||
}
|
||||
|
||||
$("#articleForm").attr("action", "${pageContext.request.contextPath}/board/updateQnA.do");
|
||||
$("#articleForm").submit();
|
||||
if(!confirm("저장하시겠습니까?")) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
</script>
|
||||
@ -89,8 +78,9 @@ function fn_update() {
|
||||
<br />
|
||||
|
||||
<form name="articleForm" id="articleForm"
|
||||
action="${pageContext.request.contextPath}/board/upateQnA.do"
|
||||
method="post">
|
||||
action="${pageContext.request.contextPath}/board/updateQnA.do"
|
||||
method="post"
|
||||
onsubmit="return fn_update();">
|
||||
|
||||
<!-- HIDDEN 영역 : 시작 -->
|
||||
<input type="text" name="pageIndex" id="pageIndex" title="페이지번호" value="${pageIndex}" readonly />
|
||||
@ -109,19 +99,21 @@ function fn_update() {
|
||||
</tr>
|
||||
<tr>
|
||||
<th>작성자</th>
|
||||
<td><input type="text" name="regUserName" id="regUserName" title="제목" value="${article.regUserName}" size="100" maxlength="200" /></td>
|
||||
<td><input type="text" name="regUserName" id="regUserName" title="제목" value="${article.regUserName}" size="100" maxlength="200" required /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>이메일</th>
|
||||
<td><input type="text" name="email" id="email" title="이메일" value="${article.email}" size="100" maxlength="200" /></td>
|
||||
<td><input type="email" name="email" id="email" title="이메일" value="${article.email}" size="100" maxlength="200" required /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>기존비밀번호</th>
|
||||
<td><input type="text" name="encArticlePassword" id="encArticlePassword" title="제목" value="${encArticlePassword}" size="100" maxlength="200" readonly /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>비밀번호</th>
|
||||
<td><input type="text" name="articlePassword" id="articlePassword" title="비밀번호" value="${article.articlePassword}" size="100" maxlength="200" /></td>
|
||||
<th>비밀번호<br/>(변경시 입력)</th>
|
||||
<td><input type="text" name="articlePassword" id="articlePassword" title="비밀번호" value="${article.articlePassword}" size="100" maxlength="200" required /><br/>
|
||||
* 비밀번호 : SHA-256 암호화 처리 후, DB에 저장되며, 웹 화면에 표출될 때는 Aria로 AuthKey를 Salt값으로 하여 재암호화처리하고 BASE64로 다시한번 인코딩하여 표출함
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>질문내용</th>
|
||||
@ -131,10 +123,9 @@ function fn_update() {
|
||||
|
||||
<br/>
|
||||
|
||||
<button name="btnNew" id="btnNew" title="취소버튼" class="float"
|
||||
onclick="fn_viewDetail('${articleNo}')">취소</button>
|
||||
<button type="submit" name="btnNew" id="btnNew" title="저장버튼" class="float"
|
||||
onsubmit="fn_update()">저장</button>
|
||||
<input type="button" name="btnNew" id="btnNew" title="취소버튼" class="float" value="취소"
|
||||
onclick="fn_viewDetail('${articleNo}')" />
|
||||
<input type="submit" name="btnNew" id="btnNew" title="저장버튼" class="float" value="저장" />
|
||||
|
||||
</form>
|
||||
|
||||
|
||||
@ -45,7 +45,25 @@ function fn_getIntValue(name, defaultValue) {
|
||||
}
|
||||
|
||||
|
||||
const POPUP_DEFAULT_WIDTH = 600; // 팝업 기본 창 가로 크기
|
||||
const POPUP_DEFAULT_HEIGHT = 600; // 팝업 기본 창 세로 크기
|
||||
|
||||
/**
|
||||
* 팝업을 생성하고 해당 URL로 접속한다.
|
||||
*
|
||||
* @param url
|
||||
* @param popName
|
||||
* @param width 생략 시 POPUP_DEFAULT_WIDTH
|
||||
* @param height 생략 시 POPUP_DEFAULT_HEIGHT
|
||||
* @returns
|
||||
*/
|
||||
function openPopup(url, popName, width, height) {
|
||||
var options = "top=10, left=10, width=" + (width?width:600) + ", height=" + (height?height:600) + ", status=no, menubar=no, toolbar=yes, resizable=no";
|
||||
var options = "top=10, left=10, width=" + (width?width:POPUP_DEFAULT_WIDTH) + ", height=" + (height?height:POPUP_DEFAULT_HEIGHT) + ", status=no, menubar=no, toolbar=yes, resizable=no";
|
||||
window.open(url, popName, options);
|
||||
}
|
||||
|
||||
function validEmail(email) {
|
||||
if(!email) return false;
|
||||
const re = /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
|
||||
return re.test(String(email).toLowerCase());
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user