My Quotes


When U were born , you cried and the world rejoiced
Live U'r life in such a way that when you go
THE WORLD SHOULD CRY






Wednesday, April 7, 2010

Creating a JCAPTCHA with struts application

JCAPTCHA stands for Java Completely Automated Public Test to tell Computers and Humans Apart.
The open source java framework for captcha definition and integration

1) Add the jcaptcha jar file into the WEB-INF/lib directory of your .war file (or) add the same into the weblogic shared libraries and create an entry in the weblogic-application.xml
<library-ref>

<library-name>jcaptcha-all-1.0-RC3</library-name>
<exact-match>false</exact-match>
</library-ref> 
Also create an entry in the config.xml file
<library>
<name>jcaptcha-all-1.0-RC3</name>
<target>AdminServer</target>
<module-type xsi:nil="true"></module-type>
<source-path>servers\AdminServer\upload\APP-INF\lib\jcaptcha-all-1.0-RC3.jar</source-path>
<security-dd-model>DDOnly</security-dd-model>
<staging-mode>nostage</staging-mode>
</library> 
 
2) Create an entry in the web.xml file
<servlet>
<servlet-name>SimpleCaptchaServlet</servlet-name>
<display-name>SimpleCaptchaServlet</display-name>
<servlet-class>com.servlet.SimpleCaptchaServlet</servlet-class>
<init-param>
<description>passing height</description>
<param-name>height</param-name>
<param-value>30</param-value>
</init-param>
<init-param>
<description>passing height</description>
<param-name>width</param-name>
<param-value>120</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>SimpleCaptchaServlet</servlet-name>
<url-pattern>/Captcha.jpg</url-pattern>
</servlet-mapping>

3) Here is the source code for the servlet. I have not implemented exception handling its up to you to integrate exception handling in this servlet
public class SimpleCaptchaServlet extends HttpServlet {
String sImgType = null;private int height = 0;private int width = 0;
public static final String CAPTCHA_KEY = "captcha_key_name";
public void init(ServletConfig servletConfig) throws ServletException {
super.init(servletConfig);
// For this servlet, supported image types are PNG and JPG.
sImgType = servletConfig.getInitParameter("ImageType");
sImgType = sImgType == null ? "png" : sImgType.trim().toLowerCase();
if (!sImgType.equalsIgnoreCase("png") && !sImgType.equalsIgnoreCase("jpg")&& !sImgType.equalsIgnoreCase("jpeg")) {
sImgType = "png";
}
height = Integer.parseInt(getServletConfig().getInitParameter("height"));
width = Integer.parseInt(getServletConfig().getInitParameter("width"));
}
protected void doGet(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException {
ByteArrayOutputStream imgOutputStream = null;
byte[] captchaBytes = null;BufferedImage image = null;Graphics2D graphics2D = null;
Hashtable<TextAttribute, Object> map = null;Random r = null;String token = null;String ch = null;
Color c = null;GradientPaint gp = null;Font font = null;
if (request.getQueryString() != null&& request.getQueryString().indexOf("CSRF=") == -1) {
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,"GET request should have no query string.");return;
}
try {
imgOutputStream = new ByteArrayOutputStream();
image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
graphics2D = image.createGraphics(); map = new Hashtable<TextAttribute, Object>();
r = new Random(); token = Long.toString(Math.abs(r.nextLong()), 36);
ch = token.substring(0, 6);
c = new Color(0.6662f, 0.4569f, 0.3232f);
gp = new GradientPaint(30, 30, c, 15, 25, Color.white, true);
graphics2D.setPaint(gp);font = new Font("Verdana", Font.CENTER_BASELINE, 26);
graphics2D.setFont(font);graphics2D.drawString(ch, 2, 20);graphics2D.dispose();
request.getSession().setAttribute(CAPTCHA_KEY, ch);
} catch (CaptchaServiceException cse) {
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
"Problem generating captcha image.");
return;
} finally {
// Set appropriate http headers.
response.setHeader("Cache-Control", "no-store");response.setHeader("Pragma", "no-cache");
response.setDateHeader("Expires", 0);
response.setContentType("image/"+ (sImgType.equalsIgnoreCase("png") ? "png" : "jpeg"));
OutputStream outputStream = response.getOutputStream();
ImageIO.write(image, sImgType, outputStream);
outputStream.close();imgOutputStream = null;aptchaBytes = null;
image = null;graphics2D = null;map = null;r = null;token = null;ch = null;c = null;gp = null;font = null;
}
}
protected void doPost(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException {// Get the request params.
String parmValue = request.getParameter("inCaptchaChars");
String sessionValue = request.getSession().getAttribute(CAPTCHA_KEY).toString();
// Check validity and consistency of the data.
if (captchaId == null || incomingCaptchaId == null !captchaId.equals(incomingCaptchaId)) {
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,"Browser must support session cookies.");
return;
}
// Validate whether input from user is correct.
boolean passedCaptchaTest = false;
try {
passedCaptchaTest = validateCaptchaWithSession(parmValue,sessionValue);
} catch (CaptchaServiceException e) {e.printStackTrace();}
// Set flag into session.
request.getSession().removeAttribute(CAPTCHA_KEY);
// Forward request to results page.
if (passedCaptchaTest) {
RequestDispatcher rd = getServletContext().getRequestDispatcher("/Login.do");
rd.forward(request, response);
} else {
RequestDispatcher rd = getServletContext().getRequestDispatcher("/logout.do");
rd.forward(request, response);
}
}
private boolean validateCaptcha(String captchaId, String inputChars) {
boolean bValidated = false;
try {
bValidated = MyCaptchaService.getInstance().validateResponseForID(captchaId, inputChars);
} catch (CaptchaServiceException cse) {}
return bValidated;
}
private boolean validateCaptchaWithSession(String paramValue, String sessionValue) {
boolean bValidated = false;
if (!paramValue.equalsIgnoreCase(sessionValue)) {
bValidated = false;
} else {
bValidated = true;
}
return bValidated;
}
}

4) In the JSP page
<input type="hidden" name="hidCaptchaID" value="<%= session.getId() %>"/>
<!-- place for simple captcha start-->
<tr><td class="normaltext" width="70%" valign="top">Enter the letters:
<img src="/SimpleCaptchaServlet" align="middle" alt="Enter the characters appearing in this image" border="1"/><a href="/">Click here</a> to re-generate </td>
<td width="30%" valign="top"><input type="text" name="inCaptchaChars"/></td>
</tr>
<!-- place for simple captcha end -->

5) This is a servlet which generates a 2D image on to the screen.

There is the other way of implementing this captcha using the OWASP simple captcha servlet which you can get it from the OWASP site.
http://www.owasp.org/index.php/JCaptcha_servlet_example.
But the image will be very blurred.

No comments :