카테고리 없음

java captcha 만들어보기

[czar] 2016. 9. 8. 17:19

web.xml 에 등록


<servlet>

<servlet-name>CaptchaServlet</servlet-name>

<servlet-class>com.common.util.CaptchaServlet</servlet-class>

</servlet>

<servlet-mapping>

<servlet-name>CaptchaServlet</servlet-name>

<url-pattern>/captcha</url-pattern>

</servlet-mapping>





package com.common.util;


import java.awt.Color;

import java.awt.Font;

import java.awt.FontMetrics;

import java.awt.Graphics2D;

import java.awt.geom.AffineTransform;

import java.awt.image.BufferedImage;

import java.io.IOException;

import java.util.Iterator;


import javax.imageio.IIOImage;

import javax.imageio.ImageIO;

import javax.imageio.ImageWriteParam;

import javax.imageio.ImageWriter;

import javax.servlet.ServletException;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import javax.servlet.http.HttpSession;


import org.apache.commons.logging.Log;

import org.apache.commons.logging.LogFactory;


public class CaptchaServlet extends HttpServlet {


private static final long serialVersionUID = 1L;

Log log = LogFactory.getLog(CaptchaServlet.class);


protected void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

HttpSession session = request.getSession(true);


response.setHeader("Pragma", "no-cache");

response.setHeader("Cache-Control", "no-cache");

response.setDateHeader("Expires", 0);

response.setDateHeader("Max-Age", 0);

response.setContentType("image/jpg");


BufferedImage bufferedImage = null;

Graphics2D g = null;


try {


Color textColor = Color.decode("#2e2e2e");


Font textFont = new Font("arial Tahoma Sans-serif", Font.BOLD, 22);

int charsToPrint = 5;

int width = request.getParameter("width") != null ? Integer.parseInt(request.getParameter("width")) : 150;

int height = request.getParameter("height") != null ? Integer.parseInt(request.getParameter("height")) : 35;


float horizMargin = 12.0f;

float imageQuality = 1.0f; // max is 1.0 (this is for jpeg)

double rotationRange = 0.1; // this is radians

bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);


g = (Graphics2D) bufferedImage.getGraphics();

//Draw an oval

//g.setColor(Color.decode("#ECEAEA"));

g.fillRect(0, 0, width, height);


g.setColor(textColor);

g.setFont(textFont);


FontMetrics fontMetrics = g.getFontMetrics();

int maxAdvance = fontMetrics.getMaxAdvance();

int fontHeight = fontMetrics.getHeight();


// i removed 1 and l and i because there are confusing to users...

// Z, z, and N also get confusing when rotated

// 0, O, and o are also confusing...

// lowercase G looks a lot like a 9 so i killed it

// this should ideally be done for every language...

// i like controlling the characters though because it helps prevent confusion

String elegibleChars = "ABCDEFGHJKLMPQRSTUVWXY23456789";

//String elegibleChars = "AEFHKLPRTX12345678";

//String elegibleChars = "0123456789";

char[] chars = elegibleChars.toCharArray();


float spaceForLetters = -horizMargin * 5 + width;

float spacePerChar = spaceForLetters / (charsToPrint - 1.5f);


AffineTransform transform = g.getTransform();


StringBuffer finalString = new StringBuffer();


for (int i = 0; i < charsToPrint; i++) {

double randomValue = Math.random();

int randomIndex = (int) Math.round(randomValue * (chars.length - 1));

char characterToShow = chars[randomIndex];

finalString.append(characterToShow);


// this is a separate canvas used for the character so that

// we can rotate it independently

int charImageWidth = maxAdvance * 2;

int charImageHeight = fontHeight * 2;

int charWidth = fontMetrics.charWidth(characterToShow);

int charDim = Math.max(maxAdvance, fontHeight);

int halfCharDim = (int) (charDim / 2);


BufferedImage charImage = null;

Graphics2D charGraphics = null;

try {


charImage = new BufferedImage(charDim, charDim, BufferedImage.TYPE_INT_ARGB);

charGraphics = charImage.createGraphics();

charGraphics.translate(halfCharDim, halfCharDim);

double angle = (Math.random() - 0.5) * rotationRange;

charGraphics.transform(AffineTransform.getRotateInstance(angle));

charGraphics.translate(-halfCharDim, -halfCharDim);

charGraphics.setColor(textColor);

charGraphics.setFont(textFont);


int charX = (int) (0.5 * charDim - 0.5 * charWidth);

charGraphics.drawString("" + characterToShow, charX, (int) ((charDim - fontMetrics.getAscent()) / 2 + fontMetrics.getAscent()));


float x = horizMargin + spacePerChar * (i) - charDim / 4.0f;

int y = (int) ((height - charDim) / 2);

//System.out.println("x=" + x + " height=" + height + " charDim=" + charDim + " y=" + y + " advance=" + maxAdvance + " fontHeight=" + fontHeight + " ascent=" + fontMetrics.getAscent());

g.drawImage(charImage, (int) x, y, charDim, charDim, null, null);


} finally {

try {

charGraphics.dispose();

} catch (Exception ex) {}

try {

charImage.flush();

} catch (Exception ex) {}

}

}

System.out.println(finalString);

log.info("captcha string : " + finalString);

//Write the image as a jpg


Iterator iter = ImageIO.getImageWritersByFormatName("JPG");

if (iter.hasNext()) {

ImageWriter writer = null;

javax.imageio.stream.ImageOutputStream imageOutputStream = null;

javax.servlet.ServletOutputStream servletOutputStream = null;

try {

writer = (ImageWriter) iter.next();

ImageWriteParam iwp = writer.getDefaultWriteParam();

iwp.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);

iwp.setCompressionQuality(imageQuality);

servletOutputStream = response.getOutputStream();

imageOutputStream = ImageIO.createImageOutputStream(servletOutputStream);

writer.setOutput(imageOutputStream);

IIOImage imageIO = new IIOImage(bufferedImage, null, null);

writer.write(null, imageIO, iwp);

} catch (Exception ex) {

writer.abort();

} finally {//modified to prevent too many open files error

if (writer != null) {

writer.dispose();

}

try {

imageOutputStream.close();

} catch (Exception ex) {}

try {

servletOutputStream.close();

} catch (Exception ex) {}


}

} else {

log.error("CaptchaErr No Encoder Found For JSP");

throw new RuntimeException("no encoder found for jsp");

}


//ImageIO.write(bufferedImage, "jpg", response.getOutputStream());


// let's stick the final string in the session

request.getSession(true).setAttribute("captcha", finalString.toString());


} catch (Exception ioe) {

log.error("Captcha Error : " + ioe.getMessage());

throw new RuntimeException("Unable to build image", ioe);

} finally {

try {

g.dispose();

} catch (Exception ex) {}

try {

bufferedImage.flush();

} catch (Exception ex) {}

}

}


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

processRequest(request, response);

}


protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

processRequest(request, response);

}

}