serving the solutions day and night

Pages

Monday, May 10, 2010

CAPTCHA Image Code - JAVA, JSP, AJAX

CAPTCHA - Completely Automated Public Turing test to tell Computers and Humans Apart
A CAPTCHA is used to ensure that the response is not generated by a computer, means response from human. It is used to distinguish between human and bots.

HTML Form Code
<script>
 function resetCaptcha()
 {
  document.getElementById('imgCaptcha').src = 'captchaimage.aspx?' + Math.random();
 }
</script>
<div>
<img src="captchaimage.jsp" id="imgCaptcha">
<img src="refresh.jpeg" border=0 id="imgRefresh" onclick="setTimeout('resetCaptcha()', 300); return false;">
</div>

JSP CODE - captchaimage.jsp
<%@ page import="java.util.*, java.io.*,java.awt.*,java.awt.image.*,javax.imageio.*,java.awt.geom.*"%>
<%
 response.setContentType("image/jpg");
  /* Define number characters contains the captcha image, declare global */
  int iTotalChars= 6;

  /* Size image iHeight and iWidth, declare globl */
  int iHeight=40;
  int iWidth=170;

  /* font style */
  Font fntStyle1 = new Font("Arial", Font.BOLD, 30);
  Font fntStyle2 = new Font("Verdana", Font.BOLD, 20);

  /* Possible random characters in the image */
  Random randChars = new Random();
  String sImageCode = (Long.toString(Math.abs(randChars.nextLong()), 36)).substring(0,iTotalChars);

  /* BufferedImage is used to create a create new image*/
  /* TYPE_INT_RGB - does not support transpatency, TYPE_INT_ARGB - support transpatency*/

  BufferedImage biImage = new BufferedImage(iWidth, iHeight, BufferedImage.TYPE_INT_RGB);
  Graphics2D g2dImage = (Graphics2D) biImage.getGraphics();

  // Draw background rectangle and noisey filled round rectangles
  int iCircle = 15;
  g2dImage.fillRect(0, 0, iWidth, iHeight);
  for ( int i = 0; i < iCircle; i++ )
  {
    g2dImage.setColor(new Color(randChars.nextInt(255),randChars.nextInt(255),randChars.nextInt(255)));
    int iRadius = (int) (Math.random() * iHeight / 2.0);
    int iX = (int) (Math.random() * iWidth - iRadius);
    int iY = (int) (Math.random() * iHeight - iRadius);
    g2dImage.fillRoundRect(iX, iY, iRadius * 2, iRadius * 2,100,100);
  }
  g2dImage.setFont(fntStyle1);
  for ( int i = 0; i < iTotalChars; i++ )
  {
    g2dImage.setColor(new Color(randChars.nextInt(255),randChars.nextInt(255),randChars.nextInt(255)));
    if (i%2==0)
      g2dImage.drawString(sImageCode.substring(i,i+1),25*i,24);
    else
      g2dImage.drawString(sImageCode.substring(i,i+1),25*i,35);
  }

  /* create jpeg image and display on the screen*/
  OutputStream osImage = response.getOutputStream();
  ImageIO.write(biImage, "jpeg", osImage);
  osImage.close();

  /* Dispose function is used destory an image object */
  g2dImage.dispose();

  session.setAttribute("dns_security_code", sImageCode);
%>

Use AJAX code to Reload CAPTCHA image in the form. Once form submitted,use JavaScript to validate CAPTCHA image text value is not empty. Then use JSP Or Servlet code to validate user input CAPTCHA image text value and SESSION value, if it both are same, then process further oterwise throw verification is not valid in the error message.

9 comments:

Robert said...

when i run your code i am getting
the below exception, but captcha image is working.

SEVERE: Servlet.service() for servlet jsp threw exception
java.lang.IllegalStateException: getOutputStream() has already been called for this response
at org.apache.catalina.connector.Response.getWriter(Response.java:610)
at org.apache.catalina.connector.ResponseFacade.getWriter(ResponseFacade.java:198)
at org.apache.jasper.runtime.JspWriterImpl.initOut(JspWriterImpl.java:125)
at org.apache.jasper.runtime.JspWriterImpl.flushBuffer(JspWriterImpl.java:118)
at org.apache.jasper.runtime.PageContextImpl.release(PageContextImpl.java:188)
at org.apache.jasper.runtime.JspFactoryImpl.internalReleasePageContext(JspFactoryImpl.java:118)
at org.apache.jasper.runtime.JspFactoryImpl.releasePageContext(JspFactoryImpl.java:77)
at org.apache.jsp.testPages.captcha_jsp._jspService(captcha_jsp.java:135)
at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:374)
at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:342)
at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:267)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:293)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:849)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:583)
at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:454)
at java.lang.Thread.run(Unknown Source)

makdns said...

Hello Robert


Add the below 2 lines after the session (means end of jsp page), then you won't get the error.

out.clear();

out = pageContext.pushBody();


Short explain getOutputStream() function could not be used more than once, and also it will conflict with JSP Writer's out.


In servlet, no need for the above 2 lines. Let me know does it help?

Skip Cole said...

This is Great!

I made a few small changes to make it more 'human readable.' For example, for the random numbers for the circle colors, instead of using randChars.nextInt(255) I used randChars.nextInt(55)+ 200 so the colors come out more pastel.

I'd like to incorporate this into our open source project. Is that okay?

Thanks!
Skip

makdns said...

Hello Skip

Thanks for changes.your welcome, to use your open source project.

Naresh Kumar said...

CAPTCHA is to stop the automated testing process. If any one want to struck up your application just they will use the automated test process like..( JUnit Testing) they load up all properties of the form and they will loop up the registration process.Due to this the Server will down if it exceeds the no of DB Connections.If u apply CAPTCHA for your application especially for registration process it will stop such type of things

shalu said...

i try this code n its working the way i want but ...........now how i can compare the image of captcha with the user input code for verification.............plz text me as soon as posible..............

makdns said...

Hello shalu
you see the code
session.setAttribute("dns_security_code", sImageCode);
- sImageCode will be assign to session "dns_security_code", it is image code.
-now you have to check with user input with this session.

let me know you understand it.

Anonymous said...

Hello there, I think your site could possibly be having web browser compatibility issues.
When I take a look at your blog in Safari, it looks fine however, if opening in IE, it has
some overlapping issues. I just wanted to provide you with a
quick heads up! Aside from that, wonderful site!
My web page: burberry diaper bag sale

Anonymous said...

Thanks, this is generally helpful.
Still, I followed step-by-step your method in this Core Java online training
learn Java online