2014년 1월 3일 금요일

[전자정부] Double Submit 방지 Token

전자정부 프레임워크를 사용하면서 새로고칭(F5)시, 이전 request가 중복 submit이 되는 현상이 발생한다. 
SessionStatus를 사용하여 처리하는 방법도 있지만, 잘 되지 않았다. (조금더 알아봐야 할듯.) 
웹 검색을 하다가 우연히 예전에 Struts 1.x 버전에서 Form에 Token값을 이용하여 중복 submit을 방지할 수 있는 방법을 찾아내서 나름대로 커스터마이징하였다.
package egovframework.com.cmm;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.apache.log4j.Logger;

import egovframework.rte.fdl.idgnr.impl.Base64;

/**
 * Double Submit 방지 Token 생성 클래스
 * 
 * @author bcchung
 * @since 2013.04.04
 * @version 1.0
 * @see
 * 
 *      
 * << 개정이력(Modification Information) >>
 *   
 *   수정일         수정자           수정내용
 *  -------       --------    ---------------------------
 *  2013.04.04    정백철          최초 생성
 * 
 * 

 */
public class TokenMngUtil {
 
 private static final String TOKEN_KEY = "TOKEN_KEY";
 private static final Logger logger = Logger.getLogger(TokenMngUtil.class.getName());

 /**
  * 로직처리를 위해 세션과 request에 Token 생성
  * 
  * @param request
  */
 public static void saveToken(HttpServletRequest request) {
  HttpSession session = request.getSession(true);
  long systemTime = System.currentTimeMillis();
  byte[] time = new Long(systemTime).toString().getBytes();
  byte[] id = session.getId().getBytes();
  
  try {
   MessageDigest SHA = MessageDigest.getInstance("SHA-256");
   SHA.update(id);
   SHA.update(time);

   String token = Base64.encode(SHA.digest());
   request.setAttribute(TOKEN_KEY, token);
   session.setAttribute(TOKEN_KEY, token);
   
   logger.error("#########################################################################");
   logger.error("# Generate Token Key Value = " + token + " #");
   logger.error("#########################################################################");
   
  } catch (NoSuchAlgorithmException e) {
   e.printStackTrace();
  }
 }

 /**
  * 로직처리 이후 중복방지를 위해 세션의 Token 초기화
  * 
  * @param request
  */
 public static void resetToken(HttpServletRequest request) {
  HttpSession session = request.getSession(true);

  try {
   session.removeAttribute(TOKEN_KEY);
  } catch (Exception e) {
   e.printStackTrace();
  }
 }

 /**
  * 세션과 request의 Token이 동일한지 비교
  * 
  * @param request
  * @return
  */
 public static boolean isTokenValid(HttpServletRequest request) {
  HttpSession session = request.getSession(true);
  String requestToken = request.getParameter(TOKEN_KEY);
  String sessionToken = (String) session.getAttribute(TOKEN_KEY);

  if (requestToken == null || sessionToken == null) {
   return false;
  } else {
   return requestToken.equals(sessionToken);
  }
 }
}
JSP
" />
Business Logic Controller
//조회화면
@RequestMapping("/cop/bbs/addBoardArticle.do")
public String addView() {
 /* 중복방지 Token 생성 */
 TokenMngUtil.saveToken(request);
}

//등록
@RequestMapping("/cop/bbs/insertBoardArticle.do")
public String add() {
 /* 중복방지 Token 체크 */
 if(!TokenMngUtil.isTokenValid(request)) {
  model.addAttribute("message", egovMessageSource.getMessage("errors.reflesh.notPermit"));
  return "uat/uia/EgovLoginUsr";
 }

 //등록 Impl 서비스
 insertArticle(boardVO);

 /* 중복방지 Token 초기화 */
 TokenMngUtil.resetToken(request);

}

댓글 없음:

댓글 쓰기