스프링

   자동가입을 방지하는 문자열 입력을 구현할 때, 보통 많이 사용하는 것이 simplecaptcha와 jcaptcha 라이브러리다.

 

   여기선 simplecaptcha를 이용해서 구현하는 방법을 살펴보겠다.

 

      ↓참고한 곳

   - http://simplecaptcha.sourceforge.net

   - http://winflahed.tistory.com/132

   - https://github.com/ndkhoiits/Simplecaptcha/blob/master/src/main/java/nl/captcha/servlet/CaptchaServletUtil.java

 

   먼저 필요한 jar파일을 다운로드 받아서 빌드패스에 추가해준다.

 

 simplecaptcha.zip

 

   jj-simplecaptcha.jar, jj-imaging.jar 이 두 개가 필요하다.

 

 

   빌드패스를 마쳤다면, 코딩을 시작해보자.

 

   먼저 이미지를 만들어주는 클래스다. 이게 원래 라이브러리 안에 포함되어있는 클래스 같은데,, 내가 뭔가 필요한 jar 파일을 빠드린 것 같은 느낌이다.

   그냥 난 아래와 같이 만들어줬다.

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletResponse;
 
final class CaptchaServletUtil {
     
    public static void writeImage(HttpServletResponse response, BufferedImage bi) {
         
        response.setHeader("Cache-Control", "private,no-cache,no-store");
        response.setContentType("image/png");
         
        try {
            writeImage(response.getOutputStream(), bi);
        } catch (IOException e) {
            e.printStackTrace();
        }
         
    }
 
    public static void writeImage(OutputStream os, BufferedImage bi) {
         
        try {
            ImageIO.write(bi, "png", os);
            os.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
         
    }
     
}

 

그리고나서 위 클래스를 사용하는 서블릿 클래스를 작성한다.

 

import java.io.IOException;
 
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
 
import jj.play.ns.nl.captcha.Captcha;
 
public class CaptchaServlet extends HttpServlet {
 
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
 
        try {
            // 200 * 50 에해당하는 이미지 사이즈를 지정하고, 자동가입방지 문자 길이를 설정한다.
            Captcha captcha = new Captcha.Builder(250, 60)
                                    .addText()
                                    .addBackground()
                                    .addNoise()
                                    .addBorder()
                                    .build();
 
            response.setHeader("Cache-Control", "no-store");
            response.setHeader("Pragma", "no-cache");
            // 캐쉬를 지우기 위해 헤더값을 설정
            response.setDateHeader("Expires", 0);
            // 리턴값을 image형태로 설정
            response.setContentType("image/jpeg");
            // Image를 write 한다
            CaptchaServletUtil.writeImage(response, captcha.getImage());
            // 세션에 자동가입방지 문자를 저장한다.
            request.getSession().setAttribute("correctAnswer", captcha.getAnswer());
            System.out.println("captcha 자동가입방지 문자 : " + captcha.getAnswer());
        } catch (Exception e) {
            System.out.println(e.getMessage());
            System.out.println(e.getStackTrace());
            response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
            return;
        }
 
    }
 
}

 

 

web.xml에 위의 서블릿을 등록하는 것도 잊지 말자.

 

<servlet>
    <servlet-name>CaptchaServlet</servlet-name>
    <servlet-class>packageName1.packageName2.packageName3.CaptchaServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
</servlet>
 
<servlet-mapping>
    <servlet-name>CaptchaServlet</servlet-name>
    <url-pattern>/captcha</url-pattern>
</servlet-mapping>

 

 

   마지막으로 보안 이미지를 띄울 jsp 페이지다. 참고로 이미지의 src 경로는 /captcha 앞에 <%=request.getContextPath() %>나 <c:url value='/captcha'/>를 붙여주든지 해서 프로젝트 경로를 써줘야 한다. 경로 틀리게 써놓고 "이거 왜 안되죠~?"하지 않기를.

<img src="/captcha" id="captchaImg" alt="captcha img">
<input type="text" placeholder="보안문자를 입력하세요" name="captcha">
<a onclick="imgRefresh()" id="refreshBtn">새로고침</a>

 

 

   보안 이미지가 이런 식으로 나온다면 성공이다.

   새로고침을 하고 싶다면, 새로고침 텍스트에 onclick으로 function을 걸어서 아래와 같이 해주자.

 

function imgRefresh(){
    $("#captchaImg").attr("src", "/captcha?id=" + Math.random());
}

 

  이미지 스타일을 변경하고 싶다면, http://simplecaptcha.sourceforge.net/custom_images.html 를 참고할 것.

   CaptchaServlet에서 new Captcha.Builder 부분만 약간 바꿔주면 된다.

 

 

   사용자가 입력한 값이 맞는지 틀리는지 검증하는 부분은 jsp 페이지에서 submit으로 넘어가는 자바단에서 하면 된다.

 

   CaptchaServlet에서 "correctAnswer"로 세션에 저장해놓았으니, 검증하는 부분에서 사용자가 입력한 값과 getSession("correctAnswer");에 있는 값을 비교하면 될 것이다.

//참고 사이트 http://zero-gravity.tistory.com/243

 

JSP ShoppinMall 적용한 것

CaptchaServlet

package util;



import java.io.IOException;
import java.io.PrintWriter;
import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
 
import jj.play.ns.nl.captcha.Captcha;

@WebServlet("/captcha")
public class CaptchaServlet extends HttpServlet {

	private static final long serialVersionUID = 2125643565468626422L;

	@Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
 

		
        try {
            // 200 * 50 에해당하는 이미지 사이즈를 지정하고, 자동가입방지 문자 길이를 설정한다.
            Captcha captcha = new Captcha.Builder(250, 60)
                    .addText()
                    .addBackground()
                    .addNoise()
                    .addBorder()
                    .build();
 
            response.setHeader("Cache-Control", "no-store");
            response.setHeader("Pragma", "no-cache");
            // 캐쉬를 지우기 위해 헤더값을 설정
            response.setDateHeader("Expires", 0);
            // 리턴값을 image형태로 설정
            response.setContentType("image/jpeg");
            // Image를 write 한다
            CaptchaServletUtil.writeImage(response, captcha.getImage());
            // 세션에 자동가입방지 문자를 저장한다.
            request.getSession().setAttribute("correctAnswer", captcha.getAnswer());
            System.out.println("captcha 자동가입방지 문자 : " + captcha.getAnswer());
            
          
            
        } catch (Exception e) {
            System.out.println(e.getMessage());
            System.out.println(e.getStackTrace());
            response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
            return;
        }
    
    }
 
}

 

CaptchaServletUtil

package util;

import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.OutputStream;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletResponse;
 
final class CaptchaServletUtil {
     
	
	
    public static void writeImage(HttpServletResponse response, BufferedImage bi) {
         
        response.setHeader("Cache-Control", "private,no-cache,no-store");
        response.setContentType("image/png");
         
        try {
            writeImage(response.getOutputStream(), bi);
        } catch (IOException e) {
            e.printStackTrace();
        }
         
    }
 
    public static void writeImage(OutputStream os, BufferedImage bi) {
         
        try {
            ImageIO.write(bi, "png", os);
            os.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
         
    }
     
}

 

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ page import="nl.captcha.Captcha" %>

<%

     

     String captcha = (String) session.getAttribute("captcha");  //라이브러리가 생성한 자동가입방지 문자
     request.setCharacterEncoding("UTF-8"); // Do this so we can capture non-Latin chars
    String answer = request.getParameter("answer"); //사용자 입력값
    if (captcha.equals(answer)) { //서로 비교한다.

%>
        <b>Correct!</b>
<% } else { %>
        <b>Wrong!</b>
<% } %>
//자동 등록 글 방지 
function imgRefresh(){
    $("#captchaImg").attr("src", "/captcha?id=" + Math.random());
}

//자동 등록 글 방지 
function modalImgRefresh(){
    $("#modalCaptchaImg").attr("src", "/captcha?id=" + Math.random());
}




$(document).ready(function(){
	
	
	
	//detail 페이지 보안 문자
	
	$("#captchaForm").submit(function(event){
		
		event.preventDefault();
		
		var formData =new FormData($(this)[0]);
		
		 $.ajax({
			url : "/CapCharConfirm",
		    type: 'POST',
			data:  formData,
			async: false,
		    cache: false,
			 contentType: false,
			 processData: false,
			success :function(returnData){
				var myCapcha =$("#captcha").val();
				
				if(returnData ==myCapcha){
					//alert("Correct")
					
					$("#captchaConfirm").html("<span class='label label-primary' >자동등록 글 방지 확인</span>");
					$("#captcha").val("");
					alert("정상 인증  되었습니다.");
				}else{
					alert("틀렸습니다. 다시 입력해 주세요.");
					$("#captcha").val("");
					imgRefresh();
				}
				
			},
			error :function(data){
				alert("실패");
			}
		
		 });

	});
////////////////////////////////////////////////////
	
	//modal 에서   보안 문자
	$("#modalCaptchaForm").submit(function(event){
		
		event.preventDefault();
		
		var formData =new FormData($(this)[0]);
		
		 $.ajax({
			url : "/CapCharConfirm",
		    type: 'POST',
			data:  formData,
			async: false,
		    cache: false,
			 contentType: false,
			 processData: false,
			success :function(returnData){
				var myCapcha =$("#modalCaptcha").val();
				
				if(returnData ==myCapcha){
					//alert("Correct")
					
					$("#modalCaptchaConfirm").html("<span class='label label-primary' >자동등록 글 방지 확인</span>");
					$("#modalCaptcha").val("");
					alert("정상 인증  되었습니다.");
					
	    			//모달 이미지 레프레시
	     			modalImgRefresh();
					
				}else{
					alert("틀렸습니다. 다시 입력해 주세요.");
					$("#modalCaptcha").val("");
	    			//모달 이미지 레프레시
	     			modalImgRefresh();
				}
				
			},
			error :function(data){
				alert("실패");
			}
		
		 });

	});
	
});

 

세션 이용으로 서버에  부하를 줄 수 있다.

 

스프링 적용  srping project 

 

CaptchaServletUtil

package com.macaronics.www.util.captcha;

import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.OutputStream;
 
import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletResponse;
 
final class CaptchaServletUtil {
     
    public static void writeImage(HttpServletResponse response, BufferedImage bi) {
         
        response.setHeader("Cache-Control", "private,no-cache,no-store");
        response.setContentType("image/png");
         
        try {
            writeImage(response.getOutputStream(), bi);
        } catch (IOException e) {
            e.printStackTrace();
        }
         
    }
 
    public static void writeImage(OutputStream os, BufferedImage bi) {
         
        try {
            ImageIO.write(bi, "png", os);
            os.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
         
    }
     
}

 

CaptchaServlet

package com.macaronics.www.util.captcha;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import jj.play.ns.nl.captcha.Captcha;

@Controller
public class CaptchaServlet  {
 
	private static final Logger logger =LoggerFactory.getLogger(CaptchaServlet.class);
	

	//참고 사이트 http://zero-gravity.tistory.com/243
	@ResponseBody
	@RequestMapping("/captcha")
    protected void captcha(HttpServletRequest request, HttpServletResponse response) 
    			throws ServletException, IOException {
 
        try {
            // 200 * 50 에해당하는 이미지 사이즈를 지정하고, 자동가입방지 문자 길이를 설정한다.
            Captcha captcha = new Captcha.Builder(250, 60)
                                    .addText()
                                    .addBackground()
                                    .addNoise()
                                    .addBorder()
                                    .build();
 
            response.setHeader("Cache-Control", "no-store");
            response.setHeader("Pragma", "no-cache");
            // 캐쉬를 지우기 위해 헤더값을 설정
            response.setDateHeader("Expires", 0);
            // 리턴값을 image형태로 설정
            response.setContentType("image/jpeg");
            // Image를 write 한다
            CaptchaServletUtil.writeImage(response, captcha.getImage());
            // 세션에 자동가입방지 문자를 저장한다.
            request.setAttribute("correctAnswer", captcha.getAnswer());
            
            logger.info("captcha 자동가입방지 문자 : CAPTCHA :" + captcha.getAnswer());
            
            CapCharConfirm.CAPTCHA =captcha.getAnswer();
           
            logger.info("CAPTCHA CAPTCHA :" + CapCharConfirm.CAPTCHA);
         
        } catch (Exception e) {
            System.out.println(e.getMessage());
            System.out.println(e.getStackTrace());
            response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);    
        }
 
    }
	
	
	
 
}



 

CapCharConfirm

 

package com.macaronics.www.util.captcha;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
public class CapCharConfirm  {


	public static String CAPTCHA;
	private static final Logger logger =LoggerFactory.getLogger(CaptchaServlet.class);

    @ResponseBody
    @RequestMapping("/capCharConfirm")
	protected String capCharConfirm(@RequestParam(required=false) String capcha ) {
    	logger.info(" qq파라미터 값capcha :d " + capcha + " CAPTCHA : "+ CAPTCHA);
		String result ="fail";
    	if(capcha!=null){
    		logger.info(" 파라미터 값capcha : " + capcha);
    		if(capcha.equals(CAPTCHA)){
    			result ="SUCCESS";
    		}
    	}
    
		return result;
	}

    
}

 

 

//보안 문자
function imgRefresh(){

    $.ajax({    	
    	url:"/captcha",
    	type:"get",
    	success:function(result){
   		
    		    $("#captchaImg").attr("src", "/captcha?id=" + Math.random()); 			
    			
    	}    	
    });

}



$(document).ready(function(){
	
	
	

	$("#confirm").click(function(){
		var captcha=$("#captcha").val();
		
		$.ajax({
			url:"/capCharConfirm?capcha="+captcha,
		   	type:"get",
	    	success:function(result){
				if(result=="SUCCESS"){		
					$("#capchaConfirmvalue").text("로봇이 아닙니다.");
					$("#captcha").val("");
					
				}else{
					$("#captcha").val("");
					imgRefresh();
				}
			}
		});

		
	});
	
});	

 

HTML

 

		<div style="margin: 10px 0px 30px 0px">	
<img src="/captcha" id="captchaImg" alt="captcha img">
<input type="text" placeholder="보안문자를 입력하세요" name="captcha"  id="captcha">
<a onclick="imgRefresh()" id="refreshBtn" ><i class="glyphicon glyphicon-refresh"></i></a>

<button class="btn btn-success" id="confirm" type="button">확인</button>
</div>

 

 

about author

PHRASE

Level 60  머나먼나라

세상에서 가장 무서운 것은 가난도 걱정도 병도 아니다. 그것은 생에 대한 권태이다. -마키아벨리

댓글 ( 4)

댓글 남기기

작성