반응형
반응형

 

📝Boolean OR절 축약

int areaCode = detail.get("areaCode").asInt();
boolean isAreaCodeValid = areaCode == 1 || areaCode == 2 || areaCode == 31;

 

반응형
반응형

📝모자이크

 

<%@ 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

반응형
반응형
import java.io.File;
import java.io.FileWriter;

public class ResidentRegistrationRandomNumber {

	
	/**
	 * @param savePath  - 파일 추출 경로
	 * @param count     - 추출 개수
	 * @param startYear - 추출 시작년도
	 * @param endYear   - 추출 종료년도
	 * @param type      -  old : 1900년 ~ 1999년 / new : 2000년 이후    - 
	 */
	public void makeRandomRegistrationNumber(String savePath, 
			int count,int startYear, int endYear, String type){
		
		
		try {
			/** 파일 객체 생성 **/
			File file = new File(savePath);
			FileWriter fileWriter = new FileWriter(file, true); 

			/** 주민등록번호 랜덤 생성 **/
			for (int i = 0; i < count; i++) {
				
				String frontNumber = makeFrontNumber(startYear, endYear); // 주민 앞번호
				String backNumber = makeBackNumber(frontNumber, type);    // 주민 뒷번호
				
				String result = frontNumber + "-" + backNumber; // 앞번호 - 뒷번호
				
				fileWriter.write(result);
				fileWriter.write("\r\n");
				fileWriter.flush();

			}
			
			fileWriter.close();
			
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * @param frontNumber 주민번호 앞자리
	 * @param type        old - 1900년 ~ 1999년 / new - 2000년 이후
	 * @return 주민번호 뒷자리 생성
	 */
	private String makeBackNumber(String frontNumber ,String type) {
		
		int gender = 1; 
		
		if(type.equals("new")) gender = ((int) (Math.random() * 2 + 3));
		else if(type.equals("old")) gender = ((int) (Math.random() * 2 + 1));
		
		int birthCode = ((int) (Math.random() * 9599 + 1));
		int birthRegisterOrderNum = ((int) (Math.random() * 3 + 1));

		String birthCodeStr = "";
		
		if (birthCode < 10) birthCodeStr = "000" + String.valueOf(birthCode);
		else if (birthCode < 100) birthCodeStr = "00" + String.valueOf(birthCode);
		else if (birthCode < 1000) birthCodeStr = "0" + String.valueOf(birthCode);
		else birthCodeStr = String.valueOf(birthCode);
		
		String backNumber = String.valueOf(gender) + birthCodeStr + String.valueOf(birthRegisterOrderNum);

		int lastNumber = makeLastNum(frontNumber, backNumber);
		backNumber += String.valueOf(lastNumber);
		
		return backNumber;
		
	}
	
	/** 검증식 참고자료 **/
	// https://blog.naver.com/PostView.nhn?isHttpsRedirect=true&blogId=mumasa&logNo=222102707153 

	/**
	 * @param frontNumber - 주민 앞번호
	 * @param backNumber  - 주민 뒷번호
	 * @return 주민앞번호 및 뒷번호을 이용한 검증식으로 주민등록번호 맨 마지막 숫자 생성
	 */
	private int makeLastNum(String frontNumber, String backNumber) {

		int lastNumber;
		
		int f0 = frontNumber.charAt(0) * 2;
		int f1 = frontNumber.charAt(1) * 3;
		int f2 = frontNumber.charAt(2) * 4;
		int f3 = frontNumber.charAt(3) * 5;
		int f4 = frontNumber.charAt(4) * 6;
		int f5 = frontNumber.charAt(5) * 7;

		
		int b0 = backNumber.charAt(0) * 8;
		int b1 = backNumber.charAt(1) * 9;
		int b2 = backNumber.charAt(2) * 2;
		int b3 = backNumber.charAt(3) * 3;
		int b4 = backNumber.charAt(4) * 4;
		int b5 = backNumber.charAt(5) * 5;

		int sum = f0 + f1 + f2 + f3 + f4 + f5 + b0 + b1 + b2 + b3 + b4 + b5;
		int minus = sum % 11;
		

		if (minus == 0 || minus == 1) lastNumber = 0; // 나머지가 0 또는 1인 경우 - 0으로 분기처리 
		else lastNumber = 11 - minus;
		
		return lastNumber;
	}
	
	/**
	 * @param  startYear 시작년도
	 * @param  endYear   종료년도 
	 * @return 주민등록번호 앞자리 (※ 윤년 고려 X)
	 */
	private String makeFrontNumber(int startYear, int endYear) {
		
		/** ---- 년도 생성 ---- **/
		int rangeYear = endYear - startYear;
		int year = ((int) ((Math.random() * rangeYear) + startYear));

		String yearStr = "";
		if(year < 10) yearStr = "0" + String.valueOf(year);
		else yearStr = String.valueOf(year);
		
		/** ---- 월 생성 ---- **/
		int month = ((int) (Math.random() * 12) + 1);

		String monthStr = "";
		if (month < 10) monthStr = "0" + String.valueOf(month);
		else monthStr = String.valueOf(month);

		
		/** ---- 일 생성 ---- **/
		int day = 0;

		switch (month) {
		case 1:
			day = ((int) (Math.random() * 30 + 1));
			break;
		case 2:
			day = ((int) (Math.random() * 28 + 1));
			break;
		case 3:
			day = ((int) (Math.random() * 30 + 1));
			break;
		case 4:
			day = ((int) (Math.random() * 29 + 1));
			break;
		case 5:
			day = ((int) (Math.random() * 30 + 1));
			break;
		case 6:
			day = ((int) (Math.random() * 29 + 1));
			break;
		case 7:
			day = ((int) (Math.random() * 30 + 1));
			break;
		case 8:
			day = ((int) (Math.random() * 30 + 1));
			break;
		case 9:
			day = ((int) (Math.random() * 29 + 1));
			break;
		case 10:
			day = ((int) (Math.random() * 30 + 1));
			break;
		case 11:
			day = ((int) (Math.random() * 29 + 1));
			break;
		case 12:
			day = ((int) (Math.random() * 30 + 1));
			break;
		}

		String dayStr = "";
		
		if (day < 10) dayStr = "0" + String.valueOf(day);
		else dayStr = String.valueOf(day);

		String frontNumber = yearStr + monthStr + dayStr; // 주민번호 앞 자리
		
		return frontNumber;
	}	
}
반응형
반응형

 

package runnable_jar;

import java.text.SimpleDateFormat;
import java.util.Date;

public class ThreadGroupExample {

	public static void main(String[] args) {

		Date today = new Date();
		SimpleDateFormat yyyymmddForamt = new SimpleDateFormat("yyyyMMdd");
		
		String todayDate = yyyymmddForamt.format(today); 
		String date = "20221201";
		
		System.out.println("todayDate : " + todayDate); // 20221201
		
		int compare = todayDate.compareTo(date);

		// A.compareTo(B) 
		// A = B  → 0
		// A < B  → -1
		// A > B  → 1
		
		if     (compare > 0) System.out.println("date 날짜는 오늘 날짜 이전입니다."); 
		else if(compare < 0) System.out.println("date 날짜는 오늘 날짜 이후입니다.");
		else                 System.out.println("date 날짜는 오늘 날짜와 동일합니다.");
	}

}

// 출처 : https://soraji.github.io/java/2019/04/15/compareDATE/
package runnable_jar;

import java.text.SimpleDateFormat;
import java.util.Date;

public class ThreadGroupExample {

	public static void main(String[] args) {

		Date today = new Date();
		SimpleDateFormat yyyymmddForamt = new SimpleDateFormat("HHmmss");
		
		String todayTime = yyyymmddForamt.format(today); 
		String time = "224246";
		
		System.out.println("todayTime : " + todayTime); // 20221201
		
		int compare = todayTime.compareTo(time);

		// A.compareTo(B) 
		// A = B  → 0
		// A < B  → -1
		// A > B  → 1
		
		if     (compare > 0) System.out.println("time < 현재 시각"); 
		else if(compare < 0) System.out.println("time > 현재시각");
		else                 System.out.println("time = 현재시각");
	}

}
반응형
반응형
package global.configuration;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Properties;

import org.ini4j.Ini;
import org.ini4j.InvalidFileFormatException;

public class iniTest {

	static final String INI_PATH = "src/main/java/global/configuration/properties.ini"; 
	
	public static void main(String[] args) throws InvalidFileFormatException, IOException {
		
		/** ini4j 라이브러리 이용 하지 않기 **/
		// ini 파일 내용
		// mode = external_local

		Properties prop = new Properties();
		prop.load(new FileInputStream(INI_PATH));
        
		System.out.println(prop.getProperty("mode")); // external_local
		
		
		/** ini4j 라이브러리 사용 → 대괄호 읽을 수 있음**/
		// ini 파일 내용 
		// [mode]
		// mode = external_local

		Ini ini = new Ini();
		File iniFile = new File(INI_PATH);
		ini = new Ini(iniFile);
		
		System.out.println(ini.get("mode", "mode")); // external_local
		
		
	}

}
<!-- https://mvnrepository.com/artifact/org.ini4j/ini4j -->
<dependency>
    <groupId>org.ini4j</groupId>
    <artifactId>ini4j</artifactId>
    <version>0.5.4</version>
</dependency>
반응형
반응형
package com.lsj.chatting;

import java.net.InetAddress;
import java.net.UnknownHostException;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

/**
 * Handles requests for the application home page.
 */
@Controller
public class HomeController {
	
	@RequestMapping(value = "/getServerInfo", method = RequestMethod.GET)
	public void getServerInfo() throws UnknownHostException {
		
		System.out.println("HostName : " + InetAddress.getLocalHost().getHostName());
		System.out.println("Address : " + InetAddress.getLocalHost().getHostAddress());


        String osName = System.getProperty("os.name").toLowerCase();

        System.out.println("os.name property: " + osName);

        if (osName.contains("win")) {
            System.out.println("This is Windows");
        } else if (osName.contains("mac")) {
            System.out.println("This is Mac");
        } else if (osName.contains("nix") || osName.contains("nux") || osName.contains("aix")) {
            System.out.println("This is Unix or Linux");
        } else if (osName.contains("sunos")) {
            System.out.println("This is Solaris");
        } else {
            System.out.println("Your OS is not support!!");
        }
		
	}
	
}
반응형
반응형
@RequestMapping(value = "/downloadManual", method = RequestMethod.GET)
public void downloadManual(HttpServletResponse response) throws Exception {

    FileInputStream fileInputStream = null;
    OutputStream out = null;
    try {
        String path = linuxRootPath + "Manual.docx"; // 경로에 접근할 때 역슬래시('\') 사용

        File file = new File(path);
        response.setHeader("Content-Disposition", "attachment;filename=" + file.getName()); 
		// 다운로드 되거나 로컬에 저장되는 용도라는 정보를 알려주는 헤더                                                                                            

        fileInputStream = new FileInputStream(path); // 파일 읽어오기
        out = response.getOutputStream();

        int read = 0;
        byte[] buffer = new byte[1024];
        while ((read = fileInputStream.read(buffer)) != -1) { // 1024바이트씩 계속 읽으면서 outputStream에 저장, -1이 나오면 더이상 읽을
            out.write(buffer, 0, read);
        }
        fileInputStream.close();
        out.close();
    } catch (Exception e) {
        fileInputStream.close();
        out.close();
        throw new Exception("download error");
    } finally {
        fileInputStream.close();
        out.close();
    }
}

 

반응형
반응형
@SuppressWarnings("restriction")
@RequestMapping(value = "/pie", method = RequestMethod.POST)
public @ResponseBody void getServerInfo(HttpServletRequest request, HttpServletResponse response)
        throws IOException {
    OperatingSystemMXBean osBean = (com.sun.management.OperatingSystemMXBean) ManagementFactory
            .getOperatingSystemMXBean();

    double load = 0;

    load = osBean.getSystemCpuLoad();
    File f = new File("/");

    JSONObject systemInfoJson = new JSONObject();

	/** CPU **/
    systemInfoJson.put("cpuUsage", Math.round(load * 100.0)); // 사용량
    systemInfoJson.put("cpuIdle", (100 - Math.round(load * 100.0))); // 남은 용량

	/** HDD **/
    systemInfoJson.put("hddUsage", Math.round((f.getTotalSpace() - f.getUsableSpace()) / (1024 * 1024) / 1000.0)); // 사용량
    systemInfoJson.put("hddIdle", Math.round((f.getFreeSpace()) / (1024 * 1024) / 1000.0)); // 남은 용량

	/** MEMORY **/
    systemInfoJson.put("memoryTotal", Math.round(osBean.getTotalPhysicalMemorySize() / (1024 * 1024) / 1000.0)); // 사용량
    systemInfoJson.put("memoryFree", Math.round(osBean.getFreePhysicalMemorySize() / (1024 * 1024) / 1000.0)); // 남은 용량

    response.setContentType("application/json; charset=UTF-8");
    PrintWriter writer = null;

    writer = response.getWriter();
    writer.print(systemInfoJson);
    writer.flush();

}
반응형
반응형
public static String httpsGet(String strURL) throws Exception
{
    URL url = null;
    HttpsURLConnection con = null;
    String ret = new String();

    try {
        url = new URL(strURL);
        ignoreSsl();
        con = (HttpsURLConnection)url.openConnection();


        BufferedReader br = null;
        br = new BufferedReader(new InputStreamReader(con.getInputStream()));

        String input = null;

        while ((input = br.readLine()) != null){
            ret += input;
        }

        br.close();
    }
    catch (IOException e) {
        ExceptionUtil.getStackTrace(e);
    } finally {
        if (con != null) {
            con.disconnect();
        }
    }

    return ret;

}

 

 

public static void ignoreSsl() throws Exception{
    HostnameVerifier hv = new HostnameVerifier() {
    public boolean verify(String urlHostName, SSLSession session) 
            return true;
        }
    };
    trustAllHttpsCertificates();
    HttpsURLConnection.setDefaultHostnameVerifier(hv);
}

private static void trustAllHttpsCertificates() throws Exception {
    TrustManager[] trustAllCerts = new TrustManager[1];
    TrustManager tm = new miTM();
    trustAllCerts[0] = tm;
    SSLContext sc = SSLContext.getInstance("SSL");
    sc.init(null, trustAllCerts, null);
    HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
}

static class miTM implements TrustManager,X509TrustManager {
    public X509Certificate[] getAcceptedIssuers() {
        return null;
    }

    public boolean isServerTrusted(X509Certificate[] certs) {
        return true;
    }

    public boolean isClientTrusted(X509Certificate[] certs) {
        return true;
    }

    public void checkServerTrusted(X509Certificate[] certs, String authType)
            throws CertificateException {
        return;
    }

    public void checkClientTrusted(X509Certificate[] certs, String authType)
            throws CertificateException {
        return;
    }
}

 

 

출처 : https://ram2ram2.tistory.com/16

반응형