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

+ Recent posts