jQuery 와 Servlet을 이용한 간단한 Captcha 샘플~
잡다구리 샘플 2011. 8. 23. 15:32
Captcha 란 간단히 아래쪽 그림과 같은 기능을 하는것을 말한다.
제작해본 샘플은
서버측에서 이미지를 생성해 주고, 생성된 문자열을 세션에 저장시켜주는 기능을 수행하는 Servlet 하나와
고 서블릿을 사용하는 클라이언트 쪽 html 파일로 구성된다.
사용한 라이브러리는 랜덤 스트링 생성을 편하게 하기 위해 apache commons lang 의 RandomStringUtils 를 사용했다.
CaptchaGenServlet.java
이미지 생성시 문자열에 쓸 폰트를 클래스패스에 위치시킨 다음에 30번째 라인처럼 불러와서 폰트를 등록시킬 수 있다.
폰트 등록후 57번째 라인처럼 등록된 폰트를 불러와 쓸 수 있는데 시스템에 등록된 폰트들 이름을 확인하기 위해서는 다음과 같은 코드로 확인하면 된다.
web.xml 서블릿 설정
Captcha UI
쪽바로 입력했는지 체크하기(result.jsp)
제작해본 샘플은
서버측에서 이미지를 생성해 주고, 생성된 문자열을 세션에 저장시켜주는 기능을 수행하는 Servlet 하나와
고 서블릿을 사용하는 클라이언트 쪽 html 파일로 구성된다.
사용한 라이브러리는 랜덤 스트링 생성을 편하게 하기 위해 apache commons lang 의 RandomStringUtils 를 사용했다.
CaptchaGenServlet.java
package servlet; import java.awt.Color; import java.awt.Font; import java.awt.Graphics2D; import java.awt.GraphicsEnvironment; import java.awt.RenderingHints; import java.awt.font.FontRenderContext; import java.awt.geom.Rectangle2D; import java.awt.image.BufferedImage; import java.io.IOException; import javax.imageio.ImageIO; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.lang.RandomStringUtils; public class CaptchaGenServlet extends HttpServlet { private static final long serialVersionUID = 1L; @Override public void init() throws ServletException { super.init(); // 폰트 등록 try { Font font = Font.createFont(Font.TRUETYPE_FONT, this.getClass().getResourceAsStream("/servlet/HelveticaMedCd.ttf")); GraphicsEnvironment.getLocalGraphicsEnvironment().registerFont(font); } catch (Exception e) { e.printStackTrace(); } } public CaptchaGenServlet() { super(); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { generateCaptcha(request, response); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { generateCaptcha(request, response); } private void generateCaptcha(HttpServletRequest request, HttpServletResponse response){ try { // 알파벳 숫자섞인 5자리 문자열 생성 String randomString = RandomStringUtils.randomAlphanumeric(5).toUpperCase(); // 세션에 저장 request.getSession().setAttribute("CAPTCHA", randomString); Font font = new Font("Helvetica 67 Medium Condensed", Font.PLAIN, 50); FontRenderContext frc = new FontRenderContext(null, true, true); Rectangle2D bounds = font.getStringBounds(randomString, frc); int w = (int) bounds.getWidth(); int h = (int) bounds.getHeight(); // 이미지 생성 BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB); Graphics2D g = image.createGraphics(); g.setColor(Color.WHITE); g.fillRect(0, 0, w, h); g.setColor(new Color(113, 193, 217)); g.setFont(font); g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); g.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON); g.drawString(randomString, (float) bounds.getX(), (float) -bounds.getY()); g.dispose(); ImageIO.write(image, "png", response.getOutputStream()); } catch (IOException e) { e.printStackTrace(); } } }
이미지 생성시 문자열에 쓸 폰트를 클래스패스에 위치시킨 다음에 30번째 라인처럼 불러와서 폰트를 등록시킬 수 있다.
폰트 등록후 57번째 라인처럼 등록된 폰트를 불러와 쓸 수 있는데 시스템에 등록된 폰트들 이름을 확인하기 위해서는 다음과 같은 코드로 확인하면 된다.
Font[] fontList = GraphicsEnvironment.getLocalGraphicsEnvironment().getAllFonts(); for( Font f : fontList){ System.out.println(f.getName()); }
web.xml 서블릿 설정
<servlet> <display-name>CaptchaGenServlet</display-name> <servlet-name>CaptchaGenServlet</servlet-name> <servlet-class>servlet.CaptchaGenServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>CaptchaGenServlet</servlet-name> <url-pattern>/captcha</url-pattern> </servlet-mapping>
Captcha UI
<html> <head> <title>Captcha Test</title> <script type="text/javascript" src="/jquery-1.6.1.min.js"></script> <script> $(document).ready(function(){ create(); $("#refreshBtn").click(function(e){ e.preventDefault(); create(); }); $("#confirmBtn").click(function(e){ e.preventDefault(); $("#frm").submit(); }); function create(){ $("#captcha img").attr("src", "/captcha?"+Math.random()); } }); </script> <style> #captcha { width : 230px; height : 70px; border: 3px dotted #A3C552; text-align: center; padding: 5px; } </style> </head> <body> Catpcha Test!!! <form id="frm" action="result.jsp" method="post"> <div id="captcha"><img/></div> <br/> <input type="text" name="captchaInput"/> <button id="confirmBtn">확인</button> <button id="refreshBtn">리푸레쉬</button> </form> </body> </html>
쪽바로 입력했는지 체크하기(result.jsp)
SESSION : ${sessionScope['CAPTCHA']} PARAM : ${param.captchaInput} 통과 : ${ sessionScope['CAPTCHA'] eq param.captchaInput ? 'O' : 'X'}