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;
}
}
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;
}
}
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;
}
}
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
}
}