Captcha Programming in Java
package com.jit;
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;
/**
* @author Vinay Guntaka
* Servlet implementation class CaptchaServlet
*/
public class CaptchaServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#HttpServlet()
*/
public CaptchaServlet() {
super();
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
createCatcha(request, response);
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
createCatcha(request, response);
}
@SuppressWarnings("unchecked")
protected void createCatcha(HttpServletRequest request,HttpServletResponse response)throws ServletException, IOException {
response.setContentType("image/jpg");
try {
Color textColor = Color.white;
Font textFont = new Font("Georgia", Font.PLAIN, 18);
int charsToPrint = 6;
int width = 125;
int height = 28;
float horizMargin = 20.0f;
float imageQuality = 0.95f; // max is 1.0 (this is for jpeg)
double rotationRange = 0.7; // this is radians
BufferedImage bufferedImage = new BufferedImage(width, height,BufferedImage.TYPE_INT_RGB);
Graphics2D g = (Graphics2D) bufferedImage.getGraphics();
// Draw an oval
g.setColor(new Color(255, 153, 0));
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 = "ABCDEFGHJKLMPQRSTUVWXYabcdefhjkmnpqrstuvwxy23456789";
char[] chars = elegibleChars.toCharArray();
float spaceForLetters = -horizMargin * 2 + width;
float spacePerChar = spaceForLetters / (charsToPrint - 1.0f);
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);
int charWidth = fontMetrics.charWidth(characterToShow);
int charDim = Math.max(maxAdvance, fontHeight);
int halfCharDim = (int) (charDim / 2);
BufferedImage charImage = new BufferedImage(charDim, charDim,BufferedImage.TYPE_INT_ARGB);
Graphics2D 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 / 2.0f;
int y = (int) ((height - charDim) / 2);
g.drawImage(charImage, (int) x, y, charDim, charDim,null, null);
charGraphics.dispose();
}
// Write the image as a jpg
Iterator iter = ImageIO.getImageWritersByFormatName("JPG");
if (iter.hasNext()) {
ImageWriter writer = (ImageWriter) iter.next();
ImageWriteParam iwp = writer.getDefaultWriteParam();
iwp.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
iwp.setCompressionQuality(imageQuality);
writer.setOutput(ImageIO.createImageOutputStream(response.getOutputStream()));
IIOImage imageIO = new IIOImage(bufferedImage, null, null);
writer.write(null, imageIO, iwp);
} else {
throw new RuntimeException("no encoder found for jsp");
}
// let's stick the final string in the session
request.getSession().setAttribute("captcha", finalString.toString());
g.dispose();
} catch (IOException ioe) {
throw new RuntimeException("Unable to build image", ioe);
}
}
}
----------------------------------
Captcha.jsp
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Captcha</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<center>
<form method="post">
<table cellspacing="15">
<tr>
<td>Are you human?</td>
<td><input type="text" name="code"></td>
</tr>
</table>
<br>
<img src="CaptchaServlet">
<br><br>
<input type="submit" value="submit">
</form>
<br><br>
<%
String captcha = (String) session.getAttribute("captcha");
String code = (String) request.getParameter("code");
if (captcha != null && code != null) {
System.out.println("Captcha Code:"+captcha);
System.out.println("Code:"+code);
if (captcha.equals(code)) {
out.print("<p class='alert'>Correct</p>");
} else {
out.print("<p class='alert'>Incorrect</p>");
}
}
%>
</center>
</body>
</html>
--------------------------------
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
<display-name>Captcha</display-name>
<welcome-file-list>
<welcome-file>captcha.jsp</welcome-file>
</welcome-file-list>
<servlet>
<description></description>
<display-name>CaptchaServlet</display-name>
<servlet-name>CaptchaServlet</servlet-name>
<servlet-class>com.jit.CaptchaServlet</servlet-class>;
</servlet>
<servlet-mapping>
<servlet-name>CaptchaServlet</servlet-name>
<url-pattern>/CaptchaServlet</url-pattern>
</servlet-mapping>
</web-app>
package com.jit;
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;
/**
* @author Vinay Guntaka
* Servlet implementation class CaptchaServlet
*/
public class CaptchaServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#HttpServlet()
*/
public CaptchaServlet() {
super();
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
createCatcha(request, response);
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
createCatcha(request, response);
}
@SuppressWarnings("unchecked")
protected void createCatcha(HttpServletRequest request,HttpServletResponse response)throws ServletException, IOException {
response.setContentType("image/jpg");
try {
Color textColor = Color.white;
Font textFont = new Font("Georgia", Font.PLAIN, 18);
int charsToPrint = 6;
int width = 125;
int height = 28;
float horizMargin = 20.0f;
float imageQuality = 0.95f; // max is 1.0 (this is for jpeg)
double rotationRange = 0.7; // this is radians
BufferedImage bufferedImage = new BufferedImage(width, height,BufferedImage.TYPE_INT_RGB);
Graphics2D g = (Graphics2D) bufferedImage.getGraphics();
// Draw an oval
g.setColor(new Color(255, 153, 0));
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 = "ABCDEFGHJKLMPQRSTUVWXYabcdefhjkmnpqrstuvwxy23456789";
char[] chars = elegibleChars.toCharArray();
float spaceForLetters = -horizMargin * 2 + width;
float spacePerChar = spaceForLetters / (charsToPrint - 1.0f);
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);
int charWidth = fontMetrics.charWidth(characterToShow);
int charDim = Math.max(maxAdvance, fontHeight);
int halfCharDim = (int) (charDim / 2);
BufferedImage charImage = new BufferedImage(charDim, charDim,BufferedImage.TYPE_INT_ARGB);
Graphics2D 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 / 2.0f;
int y = (int) ((height - charDim) / 2);
g.drawImage(charImage, (int) x, y, charDim, charDim,null, null);
charGraphics.dispose();
}
// Write the image as a jpg
Iterator iter = ImageIO.getImageWritersByFormatName("JPG");
if (iter.hasNext()) {
ImageWriter writer = (ImageWriter) iter.next();
ImageWriteParam iwp = writer.getDefaultWriteParam();
iwp.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
iwp.setCompressionQuality(imageQuality);
writer.setOutput(ImageIO.createImageOutputStream(response.getOutputStream()));
IIOImage imageIO = new IIOImage(bufferedImage, null, null);
writer.write(null, imageIO, iwp);
} else {
throw new RuntimeException("no encoder found for jsp");
}
// let's stick the final string in the session
request.getSession().setAttribute("captcha", finalString.toString());
g.dispose();
} catch (IOException ioe) {
throw new RuntimeException("Unable to build image", ioe);
}
}
}
----------------------------------
Captcha.jsp
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Captcha</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<center>
<form method="post">
<table cellspacing="15">
<tr>
<td>Are you human?</td>
<td><input type="text" name="code"></td>
</tr>
</table>
<br>
<img src="CaptchaServlet">
<br><br>
<input type="submit" value="submit">
</form>
<br><br>
<%
String captcha = (String) session.getAttribute("captcha");
String code = (String) request.getParameter("code");
if (captcha != null && code != null) {
System.out.println("Captcha Code:"+captcha);
System.out.println("Code:"+code);
if (captcha.equals(code)) {
out.print("<p class='alert'>Correct</p>");
} else {
out.print("<p class='alert'>Incorrect</p>");
}
}
%>
</center>
</body>
</html>
--------------------------------
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
<display-name>Captcha</display-name>
<welcome-file-list>
<welcome-file>captcha.jsp</welcome-file>
</welcome-file-list>
<servlet>
<description></description>
<display-name>CaptchaServlet</display-name>
<servlet-name>CaptchaServlet</servlet-name>
<servlet-class>com.jit.CaptchaServlet</servlet-class>;
</servlet>
<servlet-mapping>
<servlet-name>CaptchaServlet</servlet-name>
<url-pattern>/CaptchaServlet</url-pattern>
</servlet-mapping>
</web-app>
No comments:
Post a Comment