You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user@struts.apache.org by Brian Relph <re...@gmail.com> on 2008/01/15 21:53:22 UTC

Re: captcha + struts2

I use an ImageCaptchaServlet that is generally like the one in the appfuse
example, but without the security stuff.  Also, i am usually not able to
store the captcha's based on session id, so i pass a parameter in called
'captchaId' on my request.

I register the servlet in my web.xml, and since i only need 1 captcha on a
page/request, i map it to captcha.jpg.

In my jsp, i create an image with 'captcha.jpg' as the source, along with an
input to grab the user's response.

Finally, i validate the captcha in my action.

There is quite a bit of spring configuration options for the captcha,
reference the appfuse implementation for it, or check the jcaptcha site.  I
autowire my actions by name (the default) and my jcaptchaService bean is
declared like so:

<!-- jcaptchaService is injected into ImageCaptchaServlet as well as to
jcaptchaService beans -->
<bean id="jcaptchaService" class="
com.octo.captcha.service.multitype.GenericManageableCaptchaService">
  <constructor-arg index="0">
    <ref bean="imageEngine"/>
  </constructor-arg>
  <constructor-arg index="1">
    <value>1</value>
  </constructor-arg>
  <constructor-arg index="2">
    <value>180000</value>
  </constructor-arg>
</bean>

Code snips below:

ValidateAction.java
----------------------------
private ImageCaptchaService jcaptchaService;

private Map session;

public void validate()
{
  Boolean human = jcaptchaService.validateResponseForID(captchaId,
account.getAnswer());
  if (human)
  {
    getSession().put("human", human);
  }
  else
  {
    this.addFieldError("captcha", getText("healthe.user.claim.captcha.failed
"));
  }
  return;
}

captcha.jsp
-----------------
<s:form action="getTicket" method="post">

<div class="form">
  <div class="captcha input">
    <s:url value='captcha.jpg' id="captcha">
      <s:param name="captchaId" value="captchaId" />
    </s:url>
    <img src="<s:property value="#captcha"/>" name="captcha" alt="If the
image is illegible, refresh to get another one." />
  </div>
  <div class="input">
    <s:textfield name="answer" value="" />
  </div>
</div>

<s:submit value="%{getText('healthe.user.continue')}" />



web.xml
------------
<servlet>
  <servlet-name>captcha</servlet-name>
  <servlet-class>com.cerner.healthe.struts2.captcha.ImageCaptchaServlet
</servlet-class>
  <load-on-startup>3</load-on-startup>
</servlet>

<servlet-mapping>
  <servlet-name>captcha</servlet-name>
  <url-pattern>/captcha.jpg</url-pattern>
</servlet-mapping>


ImageCaptchaServlet
-------------------------------
package com.cerner.healthe.struts2.captcha;


import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;

import com.octo.captcha.service.CaptchaServiceException;
import com.octo.captcha.service.image.ImageCaptchaService;
import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGImageEncoder;

/**
 * Servlet generates CAPTCHA jpeg images based on the JCAPTCHA package. It's
configured via spring, and requires a
 * ImageCaptchaService bean with the id=japtchaService
 *
 * @author Jason Thrasher
 */
public class ImageCaptchaServlet extends HttpServlet
{
     private static final long serialVersionUID = 3258417209566116145L;

     private Log logger = LogFactory.getLog(this.getClass());

     public void init(ServletConfig servletConfig) throws ServletException
     {
          super.init(servletConfig);
     }

     protected void doGet(HttpServletRequest httpServletRequest,
               HttpServletResponse httpServletResponse) throws
ServletException, IOException
     {
          byte[] captchaChallengeAsJpeg = null;
          // the output stream to render the captcha image as jpeg into
          ByteArrayOutputStream jpegOutputStream = new
ByteArrayOutputStream();
          try
          {
               // get the image captcha service defined via the
SpringFramework
               ApplicationContext ctx =
WebApplicationContextUtils.getRequiredWebApplicationContext
(getServletContext());
               Object bean = ctx.getBean("jcaptchaService");
               ImageCaptchaService imageCaptchaService =
(ImageCaptchaService) bean;

               // get the id that will identify the generated captcha.
               // the same id must be used to validate the response
               String captchaId = httpServletRequest.getParameter
("captchaId");
               logger.debug("captchaIdParameter: " +
httpServletRequest.getParameter("captchaId"));
               if (captchaId == null)
               {
                    // If a captcha id is not passed in, use the session id
                    captchaId = httpServletRequest.getSession().getId();
                    logger.debug("httpServletRequest.session.id: "
                              + httpServletRequest.getSession().getId());
               }

               logger.debug("captchaId: " + captchaId);
               // call the ImageCaptchaService getChallenge method
               BufferedImage challenge =
imageCaptchaService.getImageChallengeForID(captchaId,

httpServletRequest.getLocale());

               // a jpeg encoder
               JPEGImageEncoder jpegEncoder = JPEGCodec.createJPEGEncoder
(jpegOutputStream);
               jpegEncoder.encode(challenge);
          }
          catch(IllegalArgumentException e)
          {
               httpServletResponse.sendError(
HttpServletResponse.SC_NOT_FOUND);
               return;
          }
          catch(CaptchaServiceException e)
          {
               httpServletResponse.sendError(
HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
               return;
          }

          captchaChallengeAsJpeg = jpegOutputStream.toByteArray();

          // flush it in the response
          httpServletResponse.setHeader("Cache-Control", "no-store");
          httpServletResponse.setHeader("Pragma", "no-cache");
          httpServletResponse.setDateHeader("Expires", 0);
          httpServletResponse.setContentType("image/jpeg");
          ServletOutputStream responseOutputStream =
httpServletResponse.getOutputStream();
          responseOutputStream.write(captchaChallengeAsJpeg);
          responseOutputStream.flush();
          responseOutputStream.close();
     }
}

On 1/15/08, aarthyjava@yahoo.com <aa...@yahoo.com> wrote:
> hi Brian,
>
> was wondering how you were  able to use the appfuse example remving all
the acegi-related stuff.I am also trying to implement Captcha in
Struts2,Could y0u please help me on this?
>
> Thanks,
> Arthy
> Brian Relph wrote:
> >
> > Thanks for the suggestions ... I was able to use the appfuse example and
> > remove all the acegi-related security stuff
> >
> >
> > On 11/17/07, Chris Pratt <th...@gmail.com> wrote:
> >>
> >> On Nov 17, 2007 6:14 AM, Brian Relph <re...@gmail.com> wrote:
> >> > I was wondering if anyone could help with a captcha implementation in
> >> > struts2.  i have seen plenty of stuff on the acegi + captcha
> >> implementation
> >> > in appfuse, but i am not using acegi ...
> >> >
> >>
> >> I've used SimpleCaptcha in the past, but a slightly better alternative
> >> is Kaptcha (http://code.google.com/p/kaptcha/).  It's really easy to
> >> integrate and works well anywhere.
> >> (*Chris*)
> >>
> >> ---------------------------------------------------------------------
> >> To unsubscribe, e-mail: user-unsubscribe@struts.apache.org
> >> For additional commands, e-mail: user-help@struts.apache.org
> >>
> >>
> >
> >
> Quoted from:
> http://www.nabble.com/captcha-%2B-struts2-tp13809546p13826538.html
>
>