JCaptcha
다운로드 : http://sourceforge.net/projects/jcaptcha/
참고 : http://blog.kgom.kr/52
http://blog.naver.com/tyboss?Redirect=Log&logNo=70021305170&from=postView
https://jcaptcha.atlassian.net/wiki/display/general/JCaptcha+and+the+SpringFramework
다운로드 한 jcaptcha-1.0-all.jar 를 프로젝트에 포함시킨다.
CaptchaController.java
CaptchaService.java
CaptchaServiceSingleton.java
ImageCaptchaEngine.java
ImageCaptchaServlet.java
index.jsp
1. Servlet 으로 설정
ImageCaptchaEngine.java (커스터마이징 CaptchaEngine)
package com.web.common.captcha;
import java.awt.Font;
import com.octo.captcha.component.image.backgroundgenerator.BackgroundGenerator; import com.octo.captcha.component.image.backgroundgenerator.FunkyBackgroundGenerator; import com.octo.captcha.component.image.color.RandomRangeColorGenerator; import com.octo.captcha.component.image.fontgenerator.FontGenerator; import com.octo.captcha.component.image.fontgenerator.RandomFontGenerator; import com.octo.captcha.component.image.textpaster.RandomTextPaster; import com.octo.captcha.component.image.textpaster.TextPaster; import com.octo.captcha.component.image.wordtoimage.ComposedWordToImage; import com.octo.captcha.component.image.wordtoimage.WordToImage; import com.octo.captcha.component.word.wordgenerator.RandomWordGenerator; import com.octo.captcha.component.word.wordgenerator.WordGenerator; import com.octo.captcha.engine.image.ListImageCaptchaEngine; import com.octo.captcha.image.gimpy.GimpyFactory;
public class ImageCaptchaEngine extends ListImageCaptchaEngine { protected void buildInitialFactories() { // 랜덤 문자 설정 WordGenerator wgen = new RandomWordGenerator("ABCDEFGHIJKLMNOPQRSTUVWXYZ123456789"); // Text 색 설정 RandomRangeColorGenerator cgen = new RandomRangeColorGenerator( new int[] { 0, 100 }, new int[] { 0, 100 }, new int[] { 0, 100 }); // Text 설정 (랜덤 시작 Text Size, 랜덤 종료 Text Size, 색) TextPaster textPaster = new RandomTextPaster(new Integer(4), new Integer(7), cgen, true); // 백그라운드 색 설정 RandomRangeColorGenerator bcgen = new RandomRangeColorGenerator( new int[] { 150, 255 }, new int[] { 150, 255 }, new int[] { 150, 255 }); // 백그라운드 설정 (가로 크기, 세로 크기, 색) BackgroundGenerator backgroundGenerator = new FunkyBackgroundGenerator(new Integer(150), new Integer(50), bcgen); // 백그라운드 기본 설정 // BackgroundGenerator backgroundGenerator = new FunkyBackgroundGenerator(new Integer(150), new Integer(50)); // 글꼴 설정 Font[] fontsList = new Font[] { new Font("Arial", 0, 10), new Font("Tahoma", 0, 10), new Font("Verdana", 0, 10) }; // 폰트 설정 (랜덤 시작 폰트 Size, 랜덤 종료 폰트 Size) FontGenerator fontGenerator = new RandomFontGenerator(new Integer(20), new Integer(35), fontsList); WordToImage wordToImage = new ComposedWordToImage(fontGenerator, backgroundGenerator, textPaster); this.addFactory(new GimpyFactory(wgen, wordToImage)); } }
|
CaptchaServiceSingleton.java
package com.web.common.captcha;
import com.octo.captcha.service.captchastore.FastHashMapCaptchaStore; import com.octo.captcha.service.image.DefaultManageableImageCaptchaService; import com.octo.captcha.service.image.ImageCaptchaService;
public class CaptchaServiceSingleton { private final static ImageCaptchaService instance; static { instance = new DefaultManageableImageCaptchaService(new FastHashMapCaptchaStore(), new ImageCaptchaEngine(), 180, 100000, 75000); }
public static ImageCaptchaService getInstance() { return instance; } /* // 기본 설정 그대로 사용 private static ImageCaptchaService instance = new DefaultManageableImageCaptchaService(); public static ImageCaptchaService getInstance(){ return instance; } // 기본 설정 옵션만 변경하여 사용 private static ImageCaptchaService instance = initializeService(); private static ImageCaptchaService initializeService(){ SimpleListImageCaptchaEngine engine = new SimpleListImageCaptchaEngine(); return new DefaultManageableImageCaptchaService(new FastHashMapCaptchaStore(), engine, 180, 100000, 75000); } public static ImageCaptchaService getInstance(){ return instance; } */ }
|
ImageCaptchaServlet.java
package com.web.common.captcha;
import java.awt.image.BufferedImage; import java.io.ByteArrayOutputStream; import java.io.IOException;
import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse;
import com.octo.captcha.service.CaptchaServiceException; import com.sun.image.codec.jpeg.JPEGCodec; import com.sun.image.codec.jpeg.JPEGImageEncoder;
public class ImageCaptchaServlet extends HttpServlet {
@Override public void init(ServletConfig servletConfig) throws ServletException { super.init(servletConfig); } @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { byte[] captchaChallengeAsJpeg = null; ByteArrayOutputStream jpegOutputStream = new ByteArrayOutputStream(); try { String captchaId = request.getSession().getId(); BufferedImage challenge = CaptchaServiceSingleton.getInstance().getImageChallengeForID(captchaId, request.getLocale()); JPEGImageEncoder jpegEncoder = JPEGCodec.createJPEGEncoder(jpegOutputStream); jpegEncoder.encode(challenge); } catch (IllegalArgumentException e) { response.sendError(HttpServletResponse.SC_NOT_FOUND); return; } catch (CaptchaServiceException e) { response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); return; } captchaChallengeAsJpeg = jpegOutputStream.toByteArray(); response.setHeader("Cache-Control", "no-store"); response.setHeader("Pragma", "no-cache"); response.setDateHeader("Expires", 0); response.setContentType("image/jpeg"); ServletOutputStream responseOutputStream = response.getOutputStream(); responseOutputStream.write(captchaChallengeAsJpeg); responseOutputStream.flush(); responseOutputStream.close(); } } |
web.xml
<servlet> <servlet-name>jcaptcha</servlet-name> <servlet-class>com.web.common.captcha.ImageCaptchaServlet</servlet-class> <load-on-startup>0</load-on-startup> </servlet> <servlet-mapping> <servlet-name>jcaptcha</servlet-name> <url-pattern>/jcaptcha</url-pattern> </servlet-mapping> |
JSP (HTML)
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html> <html> <head> <meta charset="UTF-8" /> <title>Insert title here</title>
<script type="text/javascript" src="<c:url value="/resources/js/jquery-1.7.1.min.js" />"></script> <script> jQuery(function($) { $('#j_captcha_response').on('keyup', function() { var _self = $(this); var val = _self.val(); if(val) { _self.val(val.toUpperCase()); } }); }); </script>
</head> <body>
<form action="<c:url value="/captcha/insert" />" method="post"> <div> <img src="<c:url value="/jcaptcha" />" style="border:1px solid #999;" /> </div> <div> <input type="text" name="j_captcha_response" id="j_captcha_response" style="ime-mode:disabled;" /> </div> <div> <input type="submit" value="전송" /> </div> </form>
</body> </html> |
CaptchaController.java (Contoller)
package com.web.captcha.controllers;
import java.util.Map;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession;
import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.support.MessageSourceAccessor; import org.springframework.stereotype.Controller; import org.springframework.ui.ModelMap; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam;
import com.octo.captcha.service.CaptchaServiceException; import com.web.common.captcha.CaptchaServiceSingleton;
@Controller("captcha.CaptchaController") @RequestMapping("captcha") public class CaptchaController {
public static final Logger log = LoggerFactory.getLogger(CaptchaController.class); @Autowired private MessageSourceAccessor messageSourceAccessor; @RequestMapping(value="index", method=RequestMethod.GET) public void index(@RequestParam Map<String, Object> paramMap, ModelMap modelMap) throws Exception { log.debug("========================================================================================="); log.debug("== paramMap : {}", paramMap); log.debug("========================================================================================="); modelMap.put("paramMap", paramMap); } @RequestMapping(value="insert", method=RequestMethod.POST) public String insert(@RequestParam Map<String, Object> paramMap, ModelMap modelMap, HttpServletRequest request, HttpSession session) throws Exception { log.debug("========================================================================================="); log.debug("== paramMap : {}", paramMap); log.debug("========================================================================================="); modelMap.put("paramMap", paramMap); Boolean isResponseCorrect = Boolean.FALSE; String captchaId = session.getId(); String jCaptchaResponse = (String)paramMap.get("j_captcha_response"); try { isResponseCorrect = CaptchaServiceSingleton.getInstance().validateResponseForID(captchaId, jCaptchaResponse); log.debug("isResponseCorrect : {}", isResponseCorrect); } catch (CaptchaServiceException e) { } return "captcha/index"; } } |
=======================================================================================================
=======================================================================================================
2. Spring 으로 설정
1. CaptchaServiceSingleton 를 CaptchaService 로 대체
CaptchaService.java
package com.web.common.captcha;
import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Service;
import com.octo.captcha.service.captchastore.FastHashMapCaptchaStore; import com.octo.captcha.service.image.DefaultManageableImageCaptchaService; import com.octo.captcha.service.image.ImageCaptchaService;
@Service @Scope(value="singleton") public class CaptchaService { private final static ImageCaptchaService instance; static { instance = new DefaultManageableImageCaptchaService(new FastHashMapCaptchaStore(), new ImageCaptchaEngine(), 180, 100000, 75000); } public ImageCaptchaService getInstance() { return instance; } /* @PostConstruct public void init() { } @PreDestroy public void close() { } */ } |
2. ImageCaptchaServlet 을 Contoller로 대체
CaptchaContoller.java
package com.web.captcha.controllers;
import java.awt.image.BufferedImage; import java.io.ByteArrayOutputStream; import java.util.Map;
import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession;
import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.support.MessageSourceAccessor; import org.springframework.stereotype.Controller; import org.springframework.ui.ModelMap; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam;
import com.octo.captcha.service.CaptchaServiceException; import com.sun.image.codec.jpeg.JPEGCodec; import com.sun.image.codec.jpeg.JPEGImageEncoder; import com.web.common.captcha.CaptchaService;
@Controller("captcha.CaptchaController") @RequestMapping("captcha") public class CaptchaController {
public static final Logger log = LoggerFactory.getLogger(CaptchaController.class); @Autowired private MessageSourceAccessor messageSourceAccessor; @Autowired private CaptchaService captchaService; @RequestMapping(value="index", method=RequestMethod.GET) public void index(@RequestParam Map<String, Object> paramMap, ModelMap modelMap) throws Exception { log.debug("========================================================================================="); log.debug("== paramMap : {}", paramMap); log.debug("========================================================================================="); modelMap.put("paramMap", paramMap); } @RequestMapping(value="jcaptcha", method=RequestMethod.GET) public void jcaptcha(@RequestParam Map<String, Object> paramMap, ModelMap modelMap, HttpServletRequest request, HttpServletResponse response, HttpSession session) throws Exception { byte[] captchaChallengeAsJpeg = null; ByteArrayOutputStream jpegOutputStream = new ByteArrayOutputStream(); try { String captchaId = session.getId(); BufferedImage challenge = captchaService.getInstance().getImageChallengeForID(captchaId, request.getLocale()); JPEGImageEncoder jpegEncoder = JPEGCodec.createJPEGEncoder(jpegOutputStream); jpegEncoder.encode(challenge); } catch (IllegalArgumentException e) { response.sendError(HttpServletResponse.SC_NOT_FOUND); return; } catch (CaptchaServiceException e) { response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); return; } captchaChallengeAsJpeg = jpegOutputStream.toByteArray(); response.setHeader("Cache-Control", "no-store"); response.setHeader("Pragma", "no-cache"); response.setDateHeader("Expires", 0); response.setContentType("image/jpeg"); ServletOutputStream responseOutputStream = response.getOutputStream(); responseOutputStream.write(captchaChallengeAsJpeg); responseOutputStream.flush(); responseOutputStream.close(); } @RequestMapping(value="insert", method=RequestMethod.POST) public String insert(@RequestParam Map<String, Object> paramMap, ModelMap modelMap, HttpServletRequest request, HttpSession session) throws Exception { log.debug("========================================================================================="); log.debug("== paramMap : {}", paramMap); log.debug("========================================================================================="); modelMap.put("paramMap", paramMap); Boolean isResponseCorrect = Boolean.FALSE; String captchaId = session.getId(); String jCaptchaResponse = (String)paramMap.get("j_captcha_response"); try { isResponseCorrect = captchaService.getInstance().validateResponseForID(captchaId, jCaptchaResponse); log.debug("isResponseCorrect : {}", isResponseCorrect); } catch (CaptchaServiceException e) { } return "captcha/index"; } }
|
3. web.xml 설정 삭제
4. jsp image url 변경
JSP (HTML)
<img src="<c:url value="/captcha/jcaptcha" />" style="border:1px solid #999;" /> |
=======================================================================================================
=======================================================================================================
3. 이미지 새로고침 추가 (Ajax - Base64)
1. CaptchaContoller Ajax (json) 추가
CaptchaController.java
package com.web.captcha.controllers;
import java.awt.image.BufferedImage; import java.io.BufferedInputStream; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.util.Map;
import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession;
import org.apache.commons.codec.binary.Base64InputStream; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.support.MessageSourceAccessor; import org.springframework.stereotype.Controller; import org.springframework.ui.ModelMap; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam;
import com.octo.captcha.service.CaptchaServiceException; import com.sun.image.codec.jpeg.JPEGCodec; import com.sun.image.codec.jpeg.JPEGImageEncoder; import com.web.common.captcha.CaptchaService;
@Controller("captcha.CaptchaController") @RequestMapping("captcha") public class CaptchaController {
public static final Logger log = LoggerFactory.getLogger(CaptchaController.class); @Autowired private MessageSourceAccessor messageSourceAccessor; @Autowired private CaptchaService captchaService; @RequestMapping(value="index", method=RequestMethod.GET) public void index(@RequestParam Map<String, Object> paramMap, ModelMap modelMap) throws Exception { log.debug("========================================================================================="); log.debug("== paramMap : {}", paramMap); log.debug("========================================================================================="); modelMap.put("paramMap", paramMap); } @RequestMapping(value="jcaptcha", method=RequestMethod.GET) public void jcaptcha(@RequestParam Map<String, Object> paramMap, ModelMap modelMap, HttpServletRequest request, HttpServletResponse response, HttpSession session) throws Exception { byte[] captchaChallengeAsJpeg = null; ByteArrayOutputStream jpegOutputStream = new ByteArrayOutputStream(); try { String captchaId = session.getId(); BufferedImage challenge = captchaService.getInstance().getImageChallengeForID(captchaId, request.getLocale()); JPEGImageEncoder jpegEncoder = JPEGCodec.createJPEGEncoder(jpegOutputStream); jpegEncoder.encode(challenge); } catch (IllegalArgumentException e) { response.sendError(HttpServletResponse.SC_NOT_FOUND); return; } catch (CaptchaServiceException e) { response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); return; } captchaChallengeAsJpeg = jpegOutputStream.toByteArray(); response.setHeader("Cache-Control", "no-store"); response.setHeader("Pragma", "no-cache"); response.setDateHeader("Expires", 0); response.setContentType("image/jpeg"); ServletOutputStream responseOutputStream = response.getOutputStream(); responseOutputStream.write(captchaChallengeAsJpeg); responseOutputStream.flush(); responseOutputStream.close(); } @RequestMapping(value="jcaptchaImage.json") public String jcaptchaImage(@RequestParam Map<String, Object> paramMap, ModelMap modelMap, HttpServletRequest request, HttpServletResponse response, HttpSession session) throws Exception { byte[] captchaChallengeAsJpeg = null; ByteArrayOutputStream jpegOutputStream = new ByteArrayOutputStream(); try { String captchaId = session.getId(); BufferedImage challenge = captchaService.getInstance().getImageChallengeForID(captchaId, request.getLocale()); JPEGImageEncoder jpegEncoder = JPEGCodec.createJPEGEncoder(jpegOutputStream); jpegEncoder.encode(challenge); } catch (IllegalArgumentException e) { response.sendError(HttpServletResponse.SC_NOT_FOUND); throw e; } catch (CaptchaServiceException e) { response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); throw e; } BufferedInputStream bis = null; ByteArrayOutputStream baos = null; try { captchaChallengeAsJpeg = jpegOutputStream.toByteArray(); BufferedInputStream captchaBis = new BufferedInputStream(new ByteArrayInputStream(captchaChallengeAsJpeg)); Base64InputStream in = new Base64InputStream(captchaBis, true); bis = new BufferedInputStream(in); baos = new ByteArrayOutputStream(); byte[] buffer = new byte[4096]; int read = 0; while ((read = bis.read(buffer)) != -1) { baos.write(buffer, 0, read); } modelMap.put("captchaCode", baos.toString()); } finally { if(baos != null) { baos.close(); } if(bis != null) { bis.close(); } } return "jsonView"; } @RequestMapping(value="insert", method=RequestMethod.POST) public String insert(@RequestParam Map<String, Object> paramMap, ModelMap modelMap, HttpServletRequest request, HttpSession session) throws Exception { log.debug("========================================================================================="); log.debug("== paramMap : {}", paramMap); log.debug("========================================================================================="); modelMap.put("paramMap", paramMap); Boolean isResponseCorrect = Boolean.FALSE; String captchaId = session.getId(); String jCaptchaResponse = (String)paramMap.get("j_captcha_response"); try { isResponseCorrect = captchaService.getInstance().validateResponseForID(captchaId, jCaptchaResponse); log.debug("isResponseCorrect : {}", isResponseCorrect); } catch (CaptchaServiceException e) { } return "captcha/index"; } } |
2. jsp 변경
JSP (HTML)
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html> <html> <head> <meta charset="UTF-8" /> <title>Insert title here</title>
<script type="text/javascript" src="<c:url value="/resources/js/jquery-1.7.1.min.js" />"></script> <script> jQuery(function($) { $('#j_captcha_response').on('keyup', function() { var _self = $(this); var val = _self.val(); if(val) { _self.val(val.toUpperCase()); } });
var _jcaptchaCarousel = $('#jcaptchaCarousel'); $('#btnCaptchaReload').on('click', function() { $.ajax({ url : '<c:url value="/captcha/jcaptchaImage.json" />', dataType : 'json', success : function(data, textStatus, jqXHR) { if(data.captchaCode) { _jcaptchaCarousel .empty() .append($('<img />', {src:'https://t1.daumcdn.net/cfile/tistory/25572D5056E6794133"<c:url value="/captcha/insert" />" method="post"> <div id="jcaptchaCarousel"></div> <div> <input type="button" value="이미지 새로고침" id="btnCaptchaReload" /> </div> <div> <input type="text" name="j_captcha_response" id="j_captcha_response" style="ime-mode:disabled;" /> </div> <div> <input type="submit" value="전송" /> </div> </form>
</body> </html> |
=====================================================================
SimpleCaptcha
홈페이지 : http://simplecaptcha.sourceforge.net/index.html
한글음성 custom : http://javaking75.blog.me/220276964082