반응형

📝모자이크

 

<%@ page language="java" contentType="text/html; charset=utf-8"
	pageEncoding="utf-8"%>
<html>
<head>

<title>Mosaic Captcha</title>


<!-- CSS -->
<link
	href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css"
	rel="stylesheet"
	integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3"
	crossorigin="anonymous">
	

<!-- JS -->
<script
	src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>

</head>

<body>
<div class="row justify-content-center">
	<div class="col-2"></div>
	<div class="col-8">

		<!-- 문제 -->
		<div class="row justify-content-center text-center">
			<div class="col-2"></div>
			<div class="col-8">
				<img src='/captcha/mosaic/question' width="500px" height="500px" />
				<div class="my-3">
					<b>검은 칸에 해당하는 사진 번호를 입력해주세요</b>
				</div>
			</div>
			<div class="col-2"></div>
		</div>

		<!-- 객관식 리스트 -->
		<div class="row text-center">
			<div class="col">
				<img src='/captcha/mosaic/multiple/choice' />
			</div>
		</div>

		<!-- 정답란 -->
		<div class="row mt-3">
			<div class="col-2"></div>
			<div class="col-8">
				<div class="row">
					<input class="form-control my-1" type="text" id="userAnswer"
						placeholder="정답번호를 입력해주세요">
				</div>
			</div>
			<div class="col-2"></div>
		</div>

		<!-- 제출 -->
		<div class="row mt-3">
			<div class="col-2"></div>
			<div class="col-8">
				<div class="row">
					<button class="btn btn-primary" onClick="showResult()">제출</button>
				</div>
			</div>
			<div class="col-2"></div>
		</div>

	</div>
	<div class="col-2"></div>
</div>
<script
	src="<%=request.getContextPath()%>/resources/js/captcha/captcha_mosaic.js"></script>

</body>
</html>

View

 

 

let checkAnswer = async () => {

	let userAnswer = document.getElementById('userAnswer').value
	
	let response = await 
	fetch("/captcha/mosaic/answer?userAnswer=" + userAnswer, {
	  method: "GET",
	});
	
	return response.json();
	
}

let showResult = () => {
	checkAnswer().then((result) => {
		if(result.response === "right") alert("정답입니다");
		else if(result.response === "wrong") alert("오답입니다");	
	});
}


$("#userAnswer").keydown(function(key) {
	if (key.keyCode == 13) {
		showResult();
	}
});

JavaScript

 

 

package com.lsj.study.controller;

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.lsj.study.util.MosaicCaptcha;


@Controller
public class CaptchaController {

	/** ------------ Mosaic CaptCha Page ------------ **/

	@GetMapping(value = "/captcha/mosaic")
	public String captchaMosaic(HttpServletRequest reques) {

		/** Referer 필요시 사용 **/
//		String referer = request.getHeader("Referer");
//		
//		if (referer.equals(rightReferer)) return "captcha/captcha_mosaic";
//		else return "captcha/wrong_page";
		
		return "captcha/captcha_mosaic";
	}

	/** ------------ Mosaic CaptCha Multiple Choice (객관식 그림) ------------ **/

	@GetMapping(value = "/captcha/mosaic/multiple/choice")
	public void getQuestionList(HttpServletResponse response, HttpSession session) throws IOException {

		MosaicCaptcha mosaicCaptcha = new MosaicCaptcha();

		/** 객관식 번호 가져오기 **/
		BufferedImage choiceNum1 = mosaicCaptcha.getMosaicQuestionImage(session);
		BufferedImage choiceNum2 = mosaicCaptcha.getMosaicQuestionImage(session);
		BufferedImage choiceNum3 = mosaicCaptcha.getMosaicQuestionImage(session);
		BufferedImage choiceNum4 = mosaicCaptcha.getMosaicAnswerImage(session);
		
		/** 화면 준비 **/
		OutputStream out = response.getOutputStream();

		/** 객관식 정보 담기 **/
		Map<String, BufferedImage> multipleChoiceMap = new HashMap<String, BufferedImage>();
		multipleChoiceMap.put("wrong1", choiceNum1);
		multipleChoiceMap.put("wrong2", choiceNum2);
		multipleChoiceMap.put("wrong3", choiceNum3);
		multipleChoiceMap.put("answer", choiceNum4);

		/** 객관식 번호 섞기 **/
		List<String> keys = new ArrayList(multipleChoiceMap.keySet());
		Collections.shuffle(keys);

		
		/** 객관식 번호 부여하기 **/
		BufferedImage questionNum1 = mosaicCaptcha.drawNumberOnMultipleChoiceImage("1"); 
		BufferedImage questionNum2 = mosaicCaptcha.drawNumberOnMultipleChoiceImage("2"); 
		BufferedImage questionNum3 = mosaicCaptcha.drawNumberOnMultipleChoiceImage("3"); 
		BufferedImage questionNum4 = mosaicCaptcha.drawNumberOnMultipleChoiceImage("4"); 


		/** key로 정답을 찾아 session 영역에 저장 **/
		int answerNum = keys.indexOf("answer");
		session.setAttribute("mosaicAnswer", answerNum + 1);
		System.out.println("Mosaic-answer : " + (answerNum + 1));

		/** 객관식 리스트 합쳐 하나의 이미지로 재구성 **/
		try {

			/** 기본 바탕화면 구성  **/
			BufferedImage mergedImage = new BufferedImage(550, 100, BufferedImage.TYPE_INT_RGB);
			Graphics2D graphics = (Graphics2D) mergedImage.getGraphics();
			graphics.setPaint(new Color(255, 255, 255));
			graphics.fillRect(0, 0, mergedImage.getWidth(), mergedImage.getHeight());

			/** 객관식 리스트 **/
			graphics.drawImage(multipleChoiceMap.get(keys.get(0)), 0, 0, null);
			graphics.drawImage(multipleChoiceMap.get(keys.get(1)), 150, 0, null);
			graphics.drawImage(multipleChoiceMap.get(keys.get(2)), 300, 0, null);
			graphics.drawImage(multipleChoiceMap.get(keys.get(3)), 450, 0, null);
			
			/** 객관식 리스트의 번호 부여 **/
			graphics.drawImage(questionNum1, 10, 0, null);
			graphics.drawImage(questionNum2, 160, 0, null);
			graphics.drawImage(questionNum3, 310, 0, null);
			graphics.drawImage(questionNum4, 460, 0, null);

			/** 화면에 출력 **/
			response.setContentType("image/png");
			ImageIO.write(mergedImage, "png", out);

		} catch (IOException ioe) {
			ioe.printStackTrace();
		}

	}

	/** ------------ Mosaic CaptCha Question (문제) ------------ **/
	@GetMapping(value = "/captcha/mosaic/question")
	public void getMosaicQuestion(HttpServletResponse response, HttpSession session)
			throws IOException {

		MosaicCaptcha mosaic = new MosaicCaptcha();

		/** 랜덤 이미지 받기 **/
		String fileImagePath = mosaic.getRandomMosaicImage(session);

		/** 자를 부분 랜덤 XY 좌표 설정 **/
		mosaic.setCutXYPoint(session);

		File file = new File(fileImagePath); // 리사이즈할 파일 정보

		int resizedWidth = 500; // 리사이즈할 가로 길이
		int resizedHeight = 500; // 리사이즈할 세로 길이

		/** 리사이징 **/
		BufferedImage blackBoxImage = mosaic.resize(file, resizedWidth, resizedHeight);

		/** 문제 낼 곳에 블랙박스 생성 **/
		int blackBoxWidth = 100;
		int blackBoxHeight = 100;

		mosaic.drawBlackBox(blackBoxImage, blackBoxWidth, blackBoxHeight, session);

		/** 화면에 뿌릴 준비 **/
		OutputStream out = response.getOutputStream();
		
		

		/** 화면에 뿌리기 **/
		response.setContentType("image/png");
		ImageIO.write(blackBoxImage, "png", out);
	}

	
	/** ------------ Mosaic CaptCha Confirm (정답 확인) ------------ **/
	
	@GetMapping(value = "/captcha/mosaic/answer")
	public @ResponseBody Map<Object, Object> confirmCaptChaMosaic(HttpServletRequest request, HttpSession session) {

		Map<Object, Object> result = new HashMap<>();
		
		/** 정답 가져오기 **/
		session = request.getSession();
		
		String answer = String.valueOf((int) session.getAttribute("mosaicAnswer")); // 정답
		String userAnswer = request.getParameter("userAnswer"); // 유저 정답

		System.out.println("Mosaic-userAnswer : " + userAnswer);
		
		/** 정답 확인 **/
		if (userAnswer.equals(answer)) result.put("response", "right");
		else result.put("response", "wrong");
		
		return result;

	}
	
}

Controller

 

package com.lsj.study.util;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpSession;

import org.springframework.core.io.ClassPathResource;

import com.lsj.study.vo.ImageVo;

public class MosaicCaptcha {

	/**
	 * @param  session : 사용자 session
	 * @return 랜덤 모자이크에 사용할 이미지 가져오기
	 */
	public String getRandomMosaicImage(HttpSession session) {

		int randomImage = (int) (Math.random() * 6) + 1;
		String filePath = "";

		
		switch (randomImage) {
		case 1:
			filePath = new ClassPathResource("image/captcha/mosaic/mosaic_1.png").getPath();
			break;
		case 2:
			filePath = new ClassPathResource("image/captcha/mosaic/mosaic_2.png").getPath();
			break;
		case 3:
			filePath = new ClassPathResource("image/captcha/mosaic/mosaic_3.png").getPath();
			break;
		case 4:
			filePath = new ClassPathResource("image/captcha/mosaic/mosaic_4.png").getPath();
			break;
		case 5:
			filePath = new ClassPathResource("image/captcha/mosaic/mosaic_5.png").getPath();
			break;
		case 6:
			filePath = new ClassPathResource("image/captcha/mosaic/mosaic_6.png").getPath();
			break;
		}

		
		URL resource = getClass().getClassLoader().getResource(filePath);
		filePath = resource.getFile();
		
		session.setAttribute("questionImagePath", filePath);
		session.setAttribute("imageNumber", randomImage);
		
		System.out.println("QuestionfilePath : " + filePath);

		return filePath;
	}

	/**
	 * @param  session : 사용자 session
	 * @return 잘못된 모자이크 이미지 만들기
	 */
	public String getWrongRandomMosaicImage(HttpSession session) {

		int questionImage = 1;
		if(session.getAttribute("imageNumber") != null)
			questionImage = (int) session.getAttribute("imageNumber");
		
		int randomImage = (int) (Math.random() * 6) + 1;

		while (true) {
			if (questionImage != randomImage)
				break;
			else
				randomImage = (int) (Math.random() * 6) + 1;
		}

		String filePath = "";

		switch (randomImage) {
		case 1:
			filePath = new ClassPathResource("image/captcha/mosaic/mosaic_1.png").getPath();
			break;
		case 2:
			filePath = new ClassPathResource("image/captcha/mosaic/mosaic_2.png").getPath();
			break;
		case 3:
			filePath = new ClassPathResource("image/captcha/mosaic/mosaic_3.png").getPath();
			break;
		case 4:
			filePath = new ClassPathResource("image/captcha/mosaic/mosaic_4.png").getPath();
			break;
		case 5:
			filePath = new ClassPathResource("image/captcha/mosaic/mosaic_5.png").getPath();
			break;
		case 6:
			filePath = new ClassPathResource("image/captcha/mosaic/mosaic_6.png").getPath();
			break;
		}
		
		URL resource = getClass().getClassLoader().getResource(filePath);
		filePath = resource.getFile();

		System.out.println("wrongFilePath : " + filePath);

		return filePath;
	}

	/**
	 * @param  file   : 리사이즈할 파일
	 * @param  width  : 리사이즈할 넓이
	 * @param  height : 리사이즈할 높이
	 * @return 리사이즈된 이미지
	 * @throws IOException
	 */
	public BufferedImage resize(File file, int width, int height) throws IOException {

		/** 이미지 가져오기 **/
		InputStream inputStream = new FileInputStream(file);

		/** 받은 이미지 읽기 **/
		BufferedImage inputImage = ImageIO.read(inputStream);

		/** 문제 이미지의 자를 부분의 크기와 위치 범위가 정해져있기 때문에 동일한 크기로 리사이징 **/
		BufferedImage outputImage = new BufferedImage(width, height, inputImage.getType());

		Graphics2D graphics2D = outputImage.createGraphics();
		graphics2D.drawImage(inputImage, 0, 0, width, height, null); // 그리기
		graphics2D.dispose(); // 자원해제

		return outputImage;

	}

	/**
	 * @param session : 사용자 session
	 * @why   모자이크로 만들 자를 이미지 X, Y 좌표를 설정
	 */
	public void setCutXYPoint(HttpSession session) {

		int cutXPoint;
		int cutYPoint;

		/** session이 안 잡힌 경우 예외처리 **/
		if (session.getAttribute("XPoint") == null || session.getAttribute("YPoint") == null) {

			cutXPoint = (int) (Math.random() * 400);
			cutYPoint = (int) (Math.random() * 400);
			session.setAttribute("XPoint", cutXPoint);
			session.setAttribute("YPoint", cutYPoint);
			/** session 영역이 존재하는 경우 **/
		} else {

			cutXPoint = (int) (Math.random() * 400);
			cutYPoint = (int) (Math.random() * 400);
			session.setAttribute("XPoint", cutXPoint);
			session.setAttribute("YPoint", cutYPoint);

		}
	}

	/**
	 * @param blackBoxImage  : 블랙박스 이미지
	 * @param blackBoxWidth  : 블랙박스 넓이
	 * @param blackBoxHeight : 블랙박스 높이
	 * @param session        : 사용자 session
	 * @why   자른 모자이크를 검은색 사각형 박스로 덮어씌우기
	 */
	public void drawBlackBox(BufferedImage blackBoxImage, int blackBoxWidth, int blackBoxHeight, HttpSession session) {

		int cutXPoint = (int) session.getAttribute("XPoint"); // 왼쪽 상단 X좌표
		int cutYPoint = (int) session.getAttribute("YPoint"); // 왼쪽 상단 Y좌표

		/** 블랙박스 그리기 **/
		Graphics graphics = blackBoxImage.getGraphics();
		graphics.setColor(Color.BLACK);
		graphics.fillRect(cutXPoint, cutYPoint, blackBoxWidth, blackBoxHeight); // 채우기 사각형
		// graphics.drawRect(cutXPoint, cutYPoint, blackBoxWidth, blackBoxHeight); // 테두리 사각형

		graphics.dispose();
	}

	/**
	 * 
	 * @param numberToDraw : 자른 객곽신 이미지 위에 그릴 숫자
	 * @return 자른 객관식 이미지 위에 객관식 번호 기입한 이미지
	 */
	public BufferedImage drawNumberOnMultipleChoiceImage(String numberToDraw) {

		/** 이미지화할 글자 설정 **/
		int imageWidth = 550; // 문제 이미지 넓이
		int imageHeight = 100; // 문제 이미지 높이
		Color color = new Color(255, 0, 0); // 글자 색
		Font font = new Font("TimeRoman", Font.PLAIN, 35); // 이미지 글체

		ImageVo stringImage = new ImageVo(imageWidth, imageHeight, color, font);

		/** 문자를 그릴 종이 만들기 **/
		BufferedImage image = getWhitePaper(stringImage);

		/** 문제 받아오기 **/
		String question = numberToDraw;

		/** 글자 이미지가 생성될 위치 선정 **/
		Graphics2D graphics2 = image.createGraphics(); // Graphics2D 와 BufferedImage는 연동 된 느낌?

		/** 글자색과 글자체 받아오기 **/
		graphics2.setColor(stringImage.getImageColor());
		graphics2.setFont(stringImage.getFont());

		/** 해당 내용으로 그리기 작업 **/
		graphics2.drawString(question, 0, 40);
		graphics2.dispose();

		return image;
	}


	/**
	 * @param  session : 사용자 session
	 * @return 문제에서 자를 이미지 가져오기
	 */
	public BufferedImage getMosaicQuestionImage(HttpSession session) throws IOException {
		MosaicCaptcha mosaic = new MosaicCaptcha();

		/** 랜덤 이미지 받기 **/
		String fileImagePath = mosaic.getWrongRandomMosaicImage(session);

		/** 리사이즈할 파일 정보 받기 **/
		File file = new File(fileImagePath);

		int resizedWidth = 500; // 리사이즈할 가로 길이
		int resizedHeight = 500; // 리사이즈할 세로 길이

		/** 리사이징 **/
		BufferedImage resizedImage = mosaic.resize(file, resizedWidth, resizedHeight);

		/** 문제 이미지의 자를 부분의 크기와 위치 설정 **/
		int cutWidth = 100; // 자를 넓이
		int cutHeight = 100; // 자를 높이
		int cutXPoint = (int) (Math.random() * 400); // 랜덤 X포인트 (자를 왼쪽 상단 위치)
		int cutYPoint = (int) (Math.random() * 400); // 랜덤 Y포인트 (자를 왼쪽 상단 위치)

		BufferedImage cutImage = resizedImage.getSubimage(cutXPoint, cutYPoint, cutWidth, cutHeight); // 잘린 이미지

		return cutImage;
	}

	/**
	 * @param  session : 사용자 session
	 * @return 잘린 정답 이미지
	 */
	public BufferedImage getMosaicAnswerImage(HttpSession session) throws IOException {
		MosaicCaptcha mosaic = new MosaicCaptcha();

		/** 문제 이미지 경로 **/
		String fileImagePath = (String) session.getAttribute("questionImagePath");

		File file = new File(fileImagePath); // 리사이즈할 파일 정보 받기

		int resizedWidth = 500; // 리사이즈할 가로 길이
		int resizedHeight = 500; // 리사이즈할 세로 길이

		/** 리사이징 **/
		BufferedImage resizedImage = mosaic.resize(file, resizedWidth, resizedHeight);

		/** 문제 이미지의 자를 부분의 크기와 위치 설정 **/
		int cutWidth = 100; // 자를 넓이
		int cutHeight = 100; // 자를 높이
		int cutXPoint = (int) session.getAttribute("XPoint"); // 왼쪽 상단 X좌표
		int cutYPoint = (int) session.getAttribute("YPoint"); // 왼쪽 상단 Y좌표

		/** 잘린 이미지 **/
		BufferedImage cutImage = resizedImage.getSubimage(cutXPoint, cutYPoint, cutWidth, cutHeight);

		return cutImage;
	}
	/**
	 * @param  customImage : 그림을 그릴 종이 설정
	 * @return 그림을 그릴 종이
	 */
	public BufferedImage getWhitePaper(ImageVo customImage) {

		// 글자를 그릴 종이 크기 설정
		int width = customImage.getImageWidth();
		int height = customImage.getImageHeight();

		BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);

		return image;
	}

}

Util

 

package com.lsj.study.vo;

import java.awt.Color;
import java.awt.Font;

public class ImageVo {

	private int imageWidth;
	private int imageHeight;
	private Color imageColor;
	private Font font;
	
	public ImageVo(int imageWidth, int imageHeight, Color imageColor, Font font) {
		this.imageWidth = imageWidth;
		this.imageHeight = imageHeight;
		this.imageColor = imageColor;
		this.font = font;
	}

	public int getImageWidth() {
		return imageWidth;
	}

	public void setImageWidth(int imageWidth) {
		this.imageWidth = imageWidth;
	}

	public int getImageHeight() {
		return imageHeight;
	}

	public void setImageHeight(int imageHeight) {
		this.imageHeight = imageHeight;
	}

	public Color getImageColor() {
		return imageColor;
	}

	public void setImageColor(Color imageColor) {
		this.imageColor = imageColor;
	}

	public Font getFont() {
		return font;
	}

	public void setFont(Font font) {
		this.font = font;
	}
	
}

Vo

 

 

📝숫자 더하기

 

<%@ page language="java" contentType="text/html; charset=utf-8"
	pageEncoding="utf-8"%>
<html>
<head>

<title>Number Captcha</title>


<!-- CSS -->
<link
	href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css"
	rel="stylesheet"
	integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3"
	crossorigin="anonymous">
	

<!-- JS -->
<script
	src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>

</head>

<body>

<div class="row justify-content-center">
	<div class="col-3"></div>
	<div class="col-6">
		<div class="row">
			<img src="/captcha/number/question" />
		</div>
		<div class="row text-center">
			<div class="col">
				<input class="form-control" id="userAnswer" type="text"
					placeholder="정답을 입력해주세요">
			</div>
			<div class="col-3">
				<button class="btn btn-primary" onClick="showResult()">제출</button>
			</div>
		</div>
		<div class="row mt-3" id="result" style="color: red;"></div>
	</div>
	<div class="col-3"></div>
</div>
<script
	src="<%=request.getContextPath()%>/resources/js/captcha/captcha_number.js"></script>

</body>
</html>

View

 

let checkAnswer = async () => {

	let userAnswer = document.getElementById('userAnswer').value
	
	let response = await 
	fetch("/captcha/number/answer?userAnswer=" + userAnswer, {
	  method: "GET",
	});
	
	return response.json();
	
}

let showResult = () => {
	checkAnswer().then((result) => {
		if(result.response === "right") alert("정답입니다");
		else if(result.response === "wrong") alert("오답입니다");	
	});
}


$("#userAnswer").keydown(function(key) {
	if (key.keyCode == 13) {
		showResult();
	}
});

JavaScript

 

package com.lsj.study.controller;

import java.awt.Color;
import java.awt.Font;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.Map;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.lsj.study.Util.NumberCaptcha;
import com.lsj.study.Vo.ImageVo;


@Controller
public class CaptchaController {

	/** ------------ Number CaptCha Page ------------ **/
	
	@GetMapping(value = "/captcha/number")
	public String captchaNumber(HttpServletRequest request) {

		/** Referer 필요시 사용 **/
//		String referer = request.getHeader("Referer");
//		
//		if (referer.equals(rightReferer)) return "captcha/captcha_number";
//		else return "captcha/wrong_page";
		
		return "captcha/captcha_number";
		
	}

	/** ------------ Number CaptCha Question (문제)------------ **/
	
	@GetMapping(value = "/captcha/number/question")
	public void getNumberCaptcha(HttpServletResponse response, HttpSession session)
			throws IOException {

		NumberCaptcha numberCaptcha = new NumberCaptcha();
		OutputStream out = response.getOutputStream(); // 현재 화면에 뿌릴 outputStream

		/** 이미지화할 글자 설정 **/
		int imageWidth = 1000; // 문제 이미지 넓이
		int imageHeight = 500; // 문제 이미지 높이
		Color color = new Color(255, 0, 0); // 글자 색
		Font font = new Font("TimeRoman", Font.PLAIN, 100); // 이미지 글체

		ImageVo stringImage = new ImageVo(imageWidth, imageHeight, color, font);

		/** 문자를 그릴 종이 만들기 **/
		BufferedImage image = numberCaptcha.getWhitePaper(stringImage);

		/** 문제 받아오기 **/
		String question = numberCaptcha.getQuestion(session);

		/** 종이(image)에 문제(questino)을 그리기 **/
		numberCaptcha.draw(image, stringImage, question);

		/** 이미지화된 글자의 content-type 설정 **/
		response.setContentType("image/png");

		/** 만든 이미지를 out(화면)에 png로 생성 **/
		ImageIO.write(image, "png", out);

	}

	/** ------------ Number CaptCha Confrim (정답 확인) ------------ **/
	@GetMapping(value = "/captcha/number/answer")
	public @ResponseBody Map<Object, Object> confirmNumberCaptcha(HttpServletRequest request, HttpSession session) {

		Map<Object, Object> result = new HashMap<>();
		
		/** 정답 가져오기 **/
		session = request.getSession();
		
		String answer = (String) session.getAttribute("answer"); // 정답
		String userAnswer = request.getParameter("userAnswer"); // 유저 정답

		/** 정답 확인 **/
		if (userAnswer.equals(answer)) result.put("response", "right");
		else result.put("response", "wrong");
		
		return result;

	}

}

Controller

 

package com.lsj.study.Util;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;

import javax.servlet.http.HttpSession;

import com.lsj.study.Vo.ImageVo;

public class NumberCaptcha {

	/**
	 * @param customImage : 글자 그릴 종이 설정
	 * @return            : 글자 그릴 종이
	 */
	public BufferedImage getWhitePaper(ImageVo customImage) {

		// 글자를 그릴 종이 크기 설정
		int width = customImage.getImageWidth();
		int height = customImage.getImageHeight();

		BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);

		return image;
	}

	/**
	 * @param  session : 사용자 session
	 * @return         : 랜덤 숫자 더하기 문제 생성
	 */
	public String getQuestion(HttpSession session) {

		// 1번째 2번째 랜덤 숫자
		int firstNum = (int) (Math.random() * 10 + 1);
		int secondNum = (int) (Math.random() * 10 + 1);

		// session에 답 저장
		int answer = firstNum + secondNum;
		session.setAttribute("answer", String.valueOf(answer));
		System.out.println("Number-answer : " + answer);
		
		// 문제 만들기
		String question = String.valueOf(firstNum) + " + " + String.valueOf(secondNum) + " = ?";

		return question;
	}
	
	/**
	 * @param image    : 그림 그릴 종이
	 * @param imageVo  : 그림 그릴 종이 설정 
	 * @param question : 그림에 그릴 문제
	 */
	public void draw(BufferedImage image, ImageVo imageVo, String question) {

		// 글자 이미지가 생성될 위치 선정
		int left = 240;
		int top = 300;

		// Graphics2D 와 BufferedImage는 연동 된 느낌?
		Graphics2D graphics = image.createGraphics();

		// 글자색과 글자체 받아오기
		graphics.setColor(imageVo.getImageColor());
		graphics.setFont(imageVo.getFont());

		// 해당 내용으로 그리기 작업
		graphics.drawString(question, left, top);
		graphics.dispose();

	}
	
}

Util

 

package com.lsj.study.Vo;

import java.awt.Color;
import java.awt.Font;

public class ImageVo {

	private int imageWidth;
	private int imageHeight;
	private Color imageColor;
	private Font font;
	
	public ImageVo(int imageWidth, int imageHeight, Color imageColor, Font font) {
		this.imageWidth = imageWidth;
		this.imageHeight = imageHeight;
		this.imageColor = imageColor;
		this.font = font;
	}

	public int getImageWidth() {
		return imageWidth;
	}

	public void setImageWidth(int imageWidth) {
		this.imageWidth = imageWidth;
	}

	public int getImageHeight() {
		return imageHeight;
	}

	public void setImageHeight(int imageHeight) {
		this.imageHeight = imageHeight;
	}

	public Color getImageColor() {
		return imageColor;
	}

	public void setImageColor(Color imageColor) {
		this.imageColor = imageColor;
	}

	public Font getFont() {
		return font;
	}

	public void setFont(Font font) {
		this.font = font;
	}
}

Vo

 

 

 

📝모자이크

 

 

📝같은 색 맞추기

<%@ page language="java" contentType="text/html; charset=utf-8"
	pageEncoding="utf-8"%>
<html>
<head>

<title>Color</title>


<!-- CSS -->
<link
	href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css"
	rel="stylesheet"
	integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3"
	crossorigin="anonymous">
	

<!-- JS -->
<script
	src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>

</head>

<body>

<div class="row justify-content-center">
	<div class="col-3"></div>
	<div class="col-6">
		<div class="row mb-3">
			<img src="/captcha/color/question" />
		</div>
		<div class="row mb-3 text-center">
			<b>위와 동일한 색상 번호를 입력해주세요</b>
		</div>
		<div class="row">
			<img src="/captcha/color/multiple/choice" />
		</div>
		<div class="row mt-4 mb-2">
			<input class="form-control" id="userAnswer" type="text"
				placeholder="정답을 입력해주세요">
		</div>
		<div class="row">
			<button class="btn btn-primary" onClick="showResult()">제출</button>
		</div>
	</div>
	<div class="col-3"></div>
</div>
<script
	src="<%=request.getContextPath()%>/resources/js/captcha/captcha_color.js"></script>

</body>
</html>

View

 

let checkAnswer = async () => {
	
	let userAnswer = document.getElementById('userAnswer').value;
	
	let response = await 
	fetch("/captcha/color/answer?userAnswer=" + userAnswer, {
	  method: "GET",
	});
	
	return response.json();
}

let showResult = () => {
	checkAnswer().then((result) => {
		if(result.response === "right") alert("정답입니다");
		else if(result.response === "wrong") alert("오답입니다");	
	});
}


$("#userAnswer").keydown(function(key) {
	if (key.keyCode === 13) {
		showResult();
	}
});

JavaScript

 

package com.lsj.study.controller;

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.lsj.study.Util.ColorCaptcha;


@Controller
public class CaptchaController {

	/** ------------ Color CaptCha Page ------------ **/

	@GetMapping(value = "/captcha/color")
	public String captchaColor(HttpServletRequest request) {

	    /** Referer 필요시 사용 **/
	    //String referer = request.getHeader("Referer");

	    //if (referer.equals(rightReferer)) return "captcha/captcha_color";
	    //else return "captcha/wrong_page";

	    return "captcha/captcha_color";

	}

	/** ------------ Color CaptCha Question (문제의 공) ------------ **/
	@GetMapping(value = "/captcha/color/question")
	public void colorQuestion(HttpServletResponse response, HttpSession session) throws IOException {

	    /** 기존에 남아있는 정답 번호 삭제 **/
	    session.removeAttribute("colorAnswer");

	    ColorCaptcha colorCaptcha = new ColorCaptcha();
	    BufferedImage questionImage = colorCaptcha.drawQuestionColorBall(600, 200, session);

	    OutputStream out = response.getOutputStream(); // response outputStream

	    /** 이미지화된 글자의 content-type 설정 **/
	    response.setContentType("image/png");

	    /** 만든 이미지를 out(화면)에 png로 생성 **/
	    ImageIO.write(questionImage, "png", out);

	}

	/** ------------ Color CaptCha Multiple Choice (선택할 공) ------------ **/
	@GetMapping(value = "/captcha/color/multiple/choice")
	public void getMultipleChoice(HttpServletResponse response,HttpSession session) throws IOException {


	    ColorCaptcha colorCaptcha = new ColorCaptcha();

	    BufferedImage wrongImage1 = colorCaptcha.drawRandomColorBall(100, 100, session);
	    BufferedImage wrongImage2 = colorCaptcha.drawRandomColorBall(100, 100, session);
	    BufferedImage wrongImage3 = colorCaptcha.drawRandomColorBall(100, 100, session);
	    BufferedImage answerImage = colorCaptcha.drawAnswerColorBall(100, 100, session);

	    OutputStream out = response.getOutputStream(); // 현재 화면에 뿌릴 outputStream


	    /** 객관식 정보 담기 **/
	    Map<String, BufferedImage> multipleChoiceMap = new HashMap<String, BufferedImage>();
	    multipleChoiceMap.put("wrong1", wrongImage1);
	    multipleChoiceMap.put("wrong2", wrongImage2);
	    multipleChoiceMap.put("wrong3", wrongImage3);
	    multipleChoiceMap.put("answer", answerImage);

	    /** 객관식 번호 섞기 **/
	    List<String> keys = new ArrayList(multipleChoiceMap.keySet());
	    Collections.shuffle(keys);


	    /** 객관식 번호 부여하기 **/
	    BufferedImage questionNum1 = colorCaptcha.drawNumberOnColorBall("1"); 
	    BufferedImage questionNum2 = colorCaptcha.drawNumberOnColorBall("2"); 
	    BufferedImage questionNum3 = colorCaptcha.drawNumberOnColorBall("3"); 
	    BufferedImage questionNum4 = colorCaptcha.drawNumberOnColorBall("4"); 


	    /** key로 정답을 찾아 session 영역에 저장 **/
	    int answerNum = keys.indexOf("answer");
	    session.setAttribute("colorAnswer", answerNum + 1);

	    System.out.println("Color-Answer : " + (answerNum + 1) );

	    /** 객관식 리스트 합쳐 하나의 이미지로 재구성 **/
	    try {

	        /** 기본 바탕화면 구성  **/
	        BufferedImage mergedImage = new BufferedImage(600, 100, BufferedImage.TYPE_INT_ARGB);
	        Graphics2D graphics = (Graphics2D) mergedImage.getGraphics();
	        graphics.setPaint(new Color(255, 255, 255));
	        graphics.fillRect(0, 0, mergedImage.getWidth(), mergedImage.getHeight());

	        /** 객관식 리스트 **/
	        graphics.drawImage(multipleChoiceMap.get(keys.get(0)), 50, 0, null);
	        graphics.drawImage(multipleChoiceMap.get(keys.get(1)), 200, 0, null);
	        graphics.drawImage(multipleChoiceMap.get(keys.get(2)), 350, 0, null);
	        graphics.drawImage(multipleChoiceMap.get(keys.get(3)), 500, 0, null);

	        /** 객관식 리스트의 번호 부여 **/
	        graphics.drawImage(questionNum1, 70, 0, null);
	        graphics.drawImage(questionNum2, 220, 0, null);
	        graphics.drawImage(questionNum3, 370, 0, null);
	        graphics.drawImage(questionNum4, 520, 0, null);

	        /** 화면에 출력 **/
	        response.setContentType("image/png");
	        ImageIO.write(mergedImage, "png", out);

	    } catch (IOException ioe) {
	        ioe.printStackTrace();
	    }

	}

	/** ------------ Color CaptCha Confirm ------------ **/
	@GetMapping(value = "/captcha/color/answer")
	public @ResponseBody Map<Object, Object> confirmCaptChaColor
	    (HttpServletRequest request,HttpSession session) {

	    Map<Object, Object> result = new HashMap<>();

	    /** 정답 가져오기 **/
	    session = request.getSession();

	    String answer = String.valueOf((int) session.getAttribute("colorAnswer")); // 정답
	    String userAnswer = request.getParameter("userAnswer");                    // 유저 정답

	    /** 정답 확인 **/
	    if (userAnswer.equals(answer)) result.put("response", "right");
	    else result.put("response", "wrong");

	    return result;
	}
}

Controller

 

 

package com.lsj.study.Util;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;

import javax.servlet.http.HttpSession;

import com.lsj.study.Vo.ImageVo;

public class ColorCaptcha {

	/**
	 * @param       : width   - 공 넓이
	 *                height  - 공 높이
	 *                session - 사용자 Session
	 * @return      : 문제로 낼 색칠된 공 이미지
	 */
	public BufferedImage drawQuestionColorBall(int width, int height, HttpSession session) {

        session.removeAttribute("colorR");
        session.removeAttribute("colorG");
        session.removeAttribute("colorB");

        BufferedImage questionImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
		Graphics2D graphics = (Graphics2D) questionImage.getGraphics();
		
		int colorR = (int) (Math.random() * 255);
		int colorG = (int) (Math.random() * 255);
		int colorB = (int) (Math.random() * 255);
		
        session.setAttribute("colorR", colorR);
        session.setAttribute("colorG", colorG);
        session.setAttribute("colorB", colorB);
		
		graphics.setColor(new Color(colorR, colorG, colorB));
        
        int xPoint = 250;
        int yPoint = 25;
        int ovalWidth = 150;
        int ovalHeight = 150;
        graphics.fillOval(xPoint, yPoint, ovalWidth, ovalHeight); // 채우기 원
        // graphics.drawOval(xPoint, yPoint, ovalWidth, ovalHeight); // 테두리 원
        
        graphics.dispose();
        
        return questionImage;
	}
	
	/**
	 * 
	 * @param       : width   - 공 넓이
	 *                height  - 공 높이
	 *                session - 사용자 Session
	 * @return      : 랜덤으로 색칠된 오답인 공 이미지
	 */
	public BufferedImage drawRandomColorBall(int width, int height, HttpSession session) {

		int answerR = 120;
		if(session.getAttribute("colorR") != null)
			answerR = (int) session.getAttribute("colorR");
		
		BufferedImage questionImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
		Graphics2D graphics = (Graphics2D) questionImage.getGraphics();
		
		
		
		/** 정답과 중복 안되게 만들기 **/
		int colorR;
		
		if(answerR > 200) colorR = (int) (Math.random() * 150);
		else if (answerR > 150)	colorR = (int) (Math.random() * 100);
		else if (answerR > 100) colorR = (int) (Math.random() * 100) + 50;
		else if (answerR > 50) 	colorR = (int) (Math.random() * 100) + 100;
		else colorR = (int) (Math.random() * 150) + 100;
		
		
		int colorG = (int) (Math.random() * 255);
		int colorB = (int) (Math.random() * 255);
		
		graphics.setPaint(new Color(255, 255, 255));
		graphics.setColor(new Color(colorR, colorG, colorB));
        
        int xPoint = 0;
        int yPoint = 0;
        int ovalWidth = 100;
        int ovalHeight = 100;
        graphics.fillOval(xPoint, yPoint, ovalWidth, ovalHeight);
        graphics.dispose();
        
        return questionImage;
	}
	
	
	/**
	 * @param       : width   - 공 넓이
	 *                height  - 공 높이
	 *                session - 사용자 Session
	 * @return      : 정답인 색공 설정
	 */
	public BufferedImage drawAnswerColorBall(int width, int height, HttpSession session) {

		int answerR = (int) session.getAttribute("colorR");
		int answerG = (int) session.getAttribute("colorG");
		int answerB = (int) session.getAttribute("colorB");
		
		System.out.println("answerR : " + answerR);
		System.out.println("answerG : " + answerG);
		System.out.println("answerB : " + answerB);
		
		BufferedImage questionImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
		Graphics2D graphics = (Graphics2D) questionImage.getGraphics();
		
		
		graphics.setPaint(new Color(255, 255, 255));
		graphics.setColor(new Color(answerR, answerG, answerB));
        
        int xPoint = 0;
        int yPoint = 0;
        int ovalWidth = 100;
        int ovalHeight = 100;
        graphics.fillOval(xPoint, yPoint, ovalWidth, ovalHeight);
        graphics.dispose();
        
        return questionImage;
	}
	
	/**
	 * @param       : NumberToDraw - 공에 그릴 숫자
	 * @return      : 오답 및 정답 색깔 공에 객관식 선택 번호 그리기
	 */
	public BufferedImage drawNumberOnColorBall(String NumberToDraw) {

		/** 이미지화할 글자 설정 **/
		int imageWidth = 550; // 문제 이미지 넓이
		int imageHeight = 100; // 문제 이미지 높이
		Color color = new Color(0, 0, 0); // 글자 색
		Font font = new Font("TimeRoman", Font.PLAIN, 25); // 이미지 글체

		ImageVo stringImage = new ImageVo(imageWidth, imageHeight, color, font);

		/** 문자를 그릴 종이 만들기 **/
		BufferedImage image = getWhitePaper(stringImage);

		/** 문제 받아오기 **/
		String question = NumberToDraw;

		/** 글자 이미지가 생성될 위치 선정 **/
		Graphics2D graphics2 = image.createGraphics(); // Graphics2D 와 BufferedImage는 연동 된 느낌?

		/** 글자색과 글자체 받아오기 **/
		graphics2.setColor(stringImage.getImageColor());
		graphics2.setFont(stringImage.getFont());

		/** 해당 내용으로 그리기 작업 **/
		graphics2.drawString(question, 0, 40);
		graphics2.dispose();

		return image;
	}

	/**
	 * @param customImage : 그림 그릴 종이 크기 설정
	 * @return            : 그림 그릴 종이
	 */
	public BufferedImage getWhitePaper(ImageVo customImage) {

		// 글자를 그릴 종이 크기 설정
		int width = customImage.getImageWidth();
		int height = customImage.getImageHeight();

		BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);

		return image;
	}
	
}

Color Ball Class

 

package com.lsj.study.Vo;

import java.awt.Color;
import java.awt.Font;

public class ImageVo {

	private int imageWidth;
	private int imageHeight;
	private Color imageColor;
	private Font font;
	
	public ImageVo(int imageWidth, int imageHeight, Color imageColor, Font font) {
		this.imageWidth = imageWidth;
		this.imageHeight = imageHeight;
		this.imageColor = imageColor;
		this.font = font;
	}

	public int getImageWidth() {
		return imageWidth;
	}

	public void setImageWidth(int imageWidth) {
		this.imageWidth = imageWidth;
	}

	public int getImageHeight() {
		return imageHeight;
	}

	public void setImageHeight(int imageHeight) {
		this.imageHeight = imageHeight;
	}

	public Color getImageColor() {
		return imageColor;
	}

	public void setImageColor(Color imageColor) {
		this.imageColor = imageColor;
	}

	public Font getFont() {
		return font;
	}

	public void setFont(Font font) {
		this.font = font;
	}
}

Vo

 

 

📝가위바위보

<%@ page language="java" contentType="text/html; charset=utf-8"
	pageEncoding="utf-8"%>
<html>
<head>

<title>Rock Paper Scissor Captcha</title>


<!-- CSS -->
<link
	href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css"
	rel="stylesheet"
	integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3"
	crossorigin="anonymous">
	

<!-- JS -->
<script
	src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>

</head>

<body>
<div class="row justify-content-center">
	<div class="col-2"></div>
	<div class="col-8">

		<!-- 문제 -->
		<div class="row justify-content-center text-center">
			<div class="col-2"></div>
			<div class="col-8">
				<img src='rock-paper-scissor/question' width="200px" height="250px" />
				<div class="my-3">
					<b>가위 바위 보에서 이기기 위해 내야하는 걸 고르세요</b>
				</div>
			</div>
			<div class="col-2"></div>
		</div>

		<!-- 객관식 리스트 -->
		<div class="row justify-content-center">
			<div class="col-2 d-flex align-items-center me-3">
				<b class="text-danger">1</b> <img
					src="/resources/image/captcha/rock_paper_scissor/rock.JPG"
					width="100px" height="100px" />
			</div>
			<div class="col-2 d-flex align-items-center me-3">
				<b class="text-danger">2</b> <img
					src="/resources/image/captcha/rock_paper_scissor/paper.JPG"
					width="100px" height="100px" />
			</div>
			<div class="col-2 d-flex align-items-center">
				<b class="text-danger">3</b> <img
					src="/resources/image/captcha/rock_paper_scissor/scissor.JPG"
					width="100px" height="100px" />
			</div>
		</div>

		<!-- 정답란 -->
		<div class="row mt-3">
			<div class="col-2"></div>
			<div class="col-8">
				<div class="row">
					<input class="form-control my-1" type="text" id="userAnswer"
						placeholder="정답번호를 입력해주세요">
				</div>
			</div>
			<div class="col-2"></div>
		</div>

		<!-- 제출 -->
		<div class="row mt-3">
			<div class="col-2"></div>
			<div class="col-8">
				<div class="row">
					<button class="btn btn-primary" onClick="showResult()">제출</button>
				</div>
			</div>
			<div class="col-2"></div>
		</div>

	</div>
	<div class="col-2"></div>
</div>
<script
	src="<%=request.getContextPath()%>/resources/js/captcha/captcha_rock_paper_scissor.js"></script>

</body>
</html>

View

 

let checkAnswer = async () => {

	let userAnswer = document.getElementById('userAnswer').value
	
	let response = await 
	fetch("/captcha/roc-paper-scissor/answer?userAnswer=" + userAnswer, {
	  method: "GET",
	});
	
	return response.json();
	
}

let showResult = () => {
	checkAnswer().then((result) => {
		if(result.response === "right") alert("정답입니다");
		else if(result.response === "wrong") alert("오답입니다");	
	});
}


$("#userAnswer").keydown(function(key) {
	if (key.keyCode == 13) {
		showResult();
	}
});

JavaScript

 

package com.lsj.study.controller;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.Map;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.lsj.study.Util.RockPaperScissorCaptcha;


@Controller
public class CaptchaController {

	/** ------------ Rock Paper Scissor CaptCha Page ------------ **/

	@GetMapping(value = "/captcha/rock-paper-scissor")
	public String rockPaperScissor(HttpServletRequest request) {
		
		/** Referer 필요시 사용 **/
//		String referer = request.getHeader("Referer");
//		
//		if (referer.equals(rightReferer)) return "captcha/captcha_rock_paper_scissor";
//		else return "captcha/wrong_page";
		
		return "captcha/captcha_rock_paper_scissor";
	}
	
	/** ------------ Rock Paper Scissor CaptCha Question ------------ **/
	
	@GetMapping(value = "/captcha/rock-paper-scissor/question")
	public void getRockPaperScissorQuestion(HttpServletResponse response, HttpSession session) throws IOException {
		
		OutputStream out = response.getOutputStream();
		
		RockPaperScissorCaptcha rockPaperScissorCaptcha = new RockPaperScissorCaptcha();
		String fileImagePath = rockPaperScissorCaptcha.getRandomImage(session);
		

		File file = new File(fileImagePath); // 리사이즈할 파일 정보

		int resizedWidth = 500; // 리사이즈할 가로 길이
		int resizedHeight = 500; // 리사이즈할 세로 길이

		/** 리사이징 **/
		BufferedImage rockPaperScissorImage = rockPaperScissorCaptcha.resize(file, resizedWidth, resizedHeight);
		
		/** 이미지화된 글자의 content-type 설정 **/
		response.setContentType("image/png");

		/** 만든 이미지를 out(화면)에 png로 생성 **/
		ImageIO.write(rockPaperScissorImage, "png", out);
		
	}

	/** ------------ Rock Paper Scissor CaptCha Confirm ------------ **/
	
	@GetMapping(value = "/captcha/roc-paper-scissor/answer")
	public @ResponseBody Map<Object, Object> confirmCaptChaRockPaperScissor(HttpServletRequest request,HttpSession session) {
		
		Map<Object, Object> result = new HashMap<>();
		
		/** 정답 가져오기 **/
		session = request.getSession();
		
		String answer = String.valueOf((int) session.getAttribute("rockPaperScissorAnswer")); // 정답
		String userAnswer = request.getParameter("userAnswer"); // 유저 정답

		
		/** 정답 확인 **/
		if (userAnswer.equals(answer)) result.put("response", "right");
		else result.put("response", "wrong");
		
		return result;

		
	}
}

Controller

 

package com.lsj.study.Util;

import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpSession;

import org.springframework.core.io.ClassPathResource;

public class RockPaperScissorCaptcha {

	/**
	 * @param  session : 사용자 session
	 * @return 가위바위보 랜덤 이미지 경로 가져오기 
	 */
	public String getRandomRockPaperScissorPath(HttpSession session) throws IOException {

		/** 기존 정답 없애기 **/
		session.removeAttribute("rockPaperScissorAnswer");
		
		/** 정답과 문제 받아오기 **/
		int randomImage = (int) (Math.random() * 3) + 1;
		String filePath = "";
		int answerNum = 0;

		switch (randomImage) {
		case 1:
			filePath = new ClassPathResource("image/captcha/rock_paper_scissor/rock.JPG").getPath();
			answerNum = 2;
			break;
		case 2:
			filePath = new ClassPathResource("image/captcha/rock_paper_scissor/paper.JPG").getPath();
			answerNum = 3;
			break;
		case 3:
			filePath = new ClassPathResource("image/captcha/rock_paper_scissor/scissor.JPG").getPath();
			answerNum = 1;
			break;
		}
		
		URL resource = getClass().getClassLoader().getResource(filePath);
		filePath = resource.getFile();
		
		session.setAttribute("rockPaperScissorAnswer", answerNum);

		return filePath;
	}

	/**
	 * @param  file   : 리사이즈할 이미지
	 * @param  width  : 리사이즈할 넓이
	 * @param  height : 리사이즈할 높이
	 * @return 리사이즈 된 이미지
	 */
	public BufferedImage resize(File file, int width, int height) throws IOException {

		/** 이미지 가져오기 **/
		InputStream inputStream = new FileInputStream(file);

		/** 받은 이미지 읽기 **/
		BufferedImage inputImage = ImageIO.read(inputStream);

		/** 내가 원하는 크기로 리사이징 **/
		BufferedImage outputImage = new BufferedImage(width, height, inputImage.getType());

		Graphics2D graphics2D = outputImage.createGraphics();
		graphics2D.drawImage(inputImage, 0, 0, width, height, null); // 그리기
		graphics2D.dispose(); // 자원해제

		return outputImage;

	}



}

Util

 

 

 

 

📝랜덤으로 Captcha Image 가져오기

<%@ page language="java" contentType="text/html; charset=utf-8"
	pageEncoding="utf-8"%>
<html>
<head>

<title>Captcha</title>


<!-- CSS -->
<link
	href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css"
	rel="stylesheet"
	integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3"
	crossorigin="anonymous">
	

<!-- JS -->
<script
	src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>

</head>

<body>
<div id="captcha"></div>
<script
	src="<%=request.getContextPath()%>/resources/js/captcha/captcha.js"></script>

</body>
</html>

View

 

$(document).ready(function() {

	captchaLinks = ["captcha/number", "captcha/mosaic", "captcha/color", "captcha/rock-paper-scissor"];
	shuffle(captchaLinks);

	var tag = "<iframe src='http://localhost:8080/" + captchaLinks[0] + "' scrolling='no' width='100%' height='100%'/>"
	var captcha = document.getElementById("captcha");

	captcha.innerHTML = tag;
});

function shuffle(array) {
	array.sort(() => Math.random() - 0.5);
}

JavaScript

 

package com.lsj.study.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;


@Controller
public class CaptchaController {

	/** ------------ CaptCha ------------ **/
	
	@GetMapping(value = "/captcha")
	public String captCha() {

		return "captcha/captcha";

	}
	
}

Java

 

 

src/main/resource → 비즈니스 로직에서의 이미지 경로
webapp/resources → JSP에서의 이미지 경로

captcha_images.zip
0.68MB

반응형