[www.richardsenior.net/projects]
If you found this useful, please enter a thankyou in the box and click the button, or just click the button if you're busy.

Captcha

captchaSpringConfig.xml

<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd"> <!-- ****************************************************************************** --> <!-- ************************** JCaptcha ******************************************* --> <!-- ****************************************************************************** --> <!-- this is a servlet you can use to display a captcha challenge. Put a box under it for the user to enter a response in a form post --> <bean name="/pub/captcha" class="com.orange.ecare.spring.mvc.controllers.captcha.CaptchaController"> <property name="captchaService" ref="captchaService" /> </bean> <!-- this is the bean you inject into your class you can query this to find out if the captch response you recieved in your form post was valid --> <bean id="captchaService" class="com.octo.captcha.service.multitype.GenericManageableCaptchaService"> <constructor-arg index="0"><ref bean="imageEngine"/></constructor-arg> <constructor-arg index="1"><value>180</value></constructor-arg> <constructor-arg index="2"><value>180000</value></constructor-arg> </bean> <bean id="imageEngine" class="com.octo.captcha.engine.GenericCaptchaEngine"> <constructor-arg index="0"> <list> <ref bean="CaptchaFactory"/> </list> </constructor-arg> </bean> <bean id="CaptchaFactory" class="com.octo.captcha.image.gimpy.GimpyFactory" > <constructor-arg><ref bean="randomWordgen"/></constructor-arg> <constructor-arg><ref bean="wordtoimage"/></constructor-arg> </bean> <bean id="randomWordgen" class="com.octo.captcha.component.word.wordgenerator.RandomWordGenerator" > <constructor-arg index="0"><value>bcdfghgklmnpqrstwxyz</value></constructor-arg> </bean> <bean id="wordtoimage" class="com.octo.captcha.component.image.wordtoimage.DeformedComposedWordToImage" > <constructor-arg index="0"><ref bean="fontGenRandom"/></constructor-arg> <constructor-arg index="1"><ref bean="backGenGrad"/></constructor-arg> <constructor-arg index="2"><ref bean="simpleWhitePaster"/></constructor-arg> <constructor-arg index="3"><ref bean="none"/></constructor-arg> <constructor-arg index="4"><ref bean="none"/></constructor-arg> <constructor-arg index="5"><ref bean="rippleDef"/></constructor-arg> </bean> <bean id="simpleWhitePaster" class="com.octo.captcha.component.image.textpaster.SimpleTextPaster" > <constructor-arg type="java.lang.Integer" index="0"> <value>6</value> </constructor-arg> <constructor-arg type="java.lang.Integer" index="1"> <value>6</value> </constructor-arg> <constructor-arg type="java.awt.Color" index="2"> <ref bean="colourDarkOrange"/> </constructor-arg> </bean> <!-- ****************************************** --> <!-- *************** Deformations ************* --> <!-- ****************************************** --> <bean id="ripple" class="com.jhlabs.image.RippleFilter" > <property name="waveType"><value>5</value></property> <property name="XAmplitude"><value>3</value></property> <property name="YAmplitude"><value>3</value></property> <property name="XWavelength"><value>10</value></property> <property name="YWavelength"><value>10</value></property> <property name="edgeAction"><value>1</value></property> </bean> <bean id="rippleDef" class="com.octo.captcha.component.image.deformation.ImageDeformationByFilters" > <constructor-arg index="0"> <list> <ref bean="ripple"/> </list> </constructor-arg> </bean> <bean id="none" class="com.octo.captcha.component.image.deformation.ImageDeformationByFilters" > <constructor-arg index="0"> <null/> </constructor-arg> </bean> <!-- ****************************************** --> <!-- *************** FONTS ******************** --> <!-- ****************************************** --> <bean name="helveticaTTF" class="org.springframework.core.io.ClassPathResource"> <constructor-arg index="0"><value>helveticaNeu.ttf</value></constructor-arg> </bean> <bean name="fontFactory" class="com.orange.ecare.spring.mvc.controllers.captcha.FontLoader"> <property name="file" ref="helveticaTTF" /> </bean> <bean id="fontGenRandom" class="com.octo.captcha.component.image.fontgenerator.RandomFontGenerator" > <constructor-arg index="0"><value>40</value></constructor-arg> <constructor-arg index="1"><value>50</value></constructor-arg> <constructor-arg index="2"> <bean factory-method="getFont" class="com.orange.ecare.spring.mvc.controllers.captcha.FontLoader" > <constructor-arg index="0"><ref bean="helveticaTTF"/></constructor-arg> </bean> </constructor-arg> <!-- <constructor-arg index="2"> <bean factory-method="getFont" class="com.orange.ecare.spring.mvc.controllers.captcha.FontLoader" /> </constructor-arg> --> </bean> <!-- ****************************************** --> <!-- ***************** Backgrounds ************ --> <!-- ****************************************** --> <!-- backgrounds use simple background, speeds up capcha --> <bean id="backGenUni" class="com.octo.captcha.component.image.backgroundgenerator.UniColorBackgroundGenerator" > <constructor-arg index="0"><value>300</value></constructor-arg> <constructor-arg index="1"><value>80</value></constructor-arg> <constructor-arg index="2"><ref bean="colourBlack"/></constructor-arg> </bean> <bean id="backGenGrad" class="com.octo.captcha.component.image.backgroundgenerator.GradientBackgroundGenerator" > <constructor-arg index="0"><value>300</value></constructor-arg> <constructor-arg index="1"><value>80</value></constructor-arg> <constructor-arg index="2"><ref bean="colourLightOrange"/></constructor-arg> <constructor-arg index="3"><ref bean="colourDarkOrange"/></constructor-arg> </bean> <!-- ****************************************** --> <!-- ***************** Colours **************** --> <!-- ****************************************** --> <bean id="colourWhite" class="java.awt.Color" > <constructor-arg type="int" index="0"><value>255</value></constructor-arg> <constructor-arg type="int" index="1"><value>255</value></constructor-arg> <constructor-arg type="int" index="2"><value>255</value></constructor-arg> </bean> <bean id="colourBlack" class="java.awt.Color" > <constructor-arg type="int" index="0"><value>0</value></constructor-arg> <constructor-arg type="int" index="1"><value>0</value></constructor-arg> <constructor-arg type="int" index="2"><value>0</value></constructor-arg> </bean> <bean id="colourDarkOrange" class="java.awt.Color" > <constructor-arg type="int" index="0"><value>255</value></constructor-arg> <constructor-arg type="int" index="1"><value>102</value></constructor-arg> <constructor-arg type="int" index="2"><value>0</value></constructor-arg> </bean> <bean id="colourLightOrange" class="java.awt.Color" > <constructor-arg type="int" index="0"><value>255</value></constructor-arg> <constructor-arg type="int" index="1"><value>154</value></constructor-arg> <constructor-arg type="int" index="2"><value>0</value></constructor-arg> </bean> </beans>

font loader

package com.orange.ecare.spring.mvc.controllers.captcha; import java.awt.Font; import org.springframework.core.io.ClassPathResource; import java.io.File; import java.io.FileInputStream; import java.util.ArrayList; import org.springframework.core.io.FileSystemResource; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import com.orange.ecare.spring.mvc.controllers.jsp.vouchers.Vouchers; public class FontLoader { /* spring */ ClassPathResource file; public ClassPathResource getFile() {return file;} public void setFile(ClassPathResource file) {this.file = file;} /* static factory method */ public static Font[] getFont(ClassPathResource file) { Log log = LogFactory.getLog(FontLoader.class.getName()); log.debug("creating font array for following resource: " + file.getDescription()); try { Font dynamicFont = Font.createFont (Font.TRUETYPE_FONT, file.getInputStream()); Font fontList[] = new Font[1]; fontList[0] = dynamicFont; return fontList; } catch (Exception e) { log.error("Exception thrown when creating font"); log.error(e.getMessage()); e.printStackTrace(); return null; } } public Font getFont() { try { System.out.println("************************************\n"); System.out.println("************************************\n"); System.out.println("************************************\n"); System.out.println("file is " + file.getClass().getName()); System.out.println("************************************\n"); System.out.println("************************************\n"); System.out.println("************************************\n"); Font dynamicFont = Font.createFont (Font.TRUETYPE_FONT, file.getInputStream()); return dynamicFont; } catch (Exception e) { e.printStackTrace(); return null; } } }

captcha controller

package com.orange.ecare.spring.mvc.controllers.captcha; import java.awt.image.BufferedImage; import java.io.ByteArrayOutputStream; import javax.servlet.ServletOutputStream; 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.web.servlet.ModelAndView; import org.springframework.web.servlet.mvc.AbstractController; import com.octo.captcha.service.CaptchaServiceException; import com.octo.captcha.service.image.ImageCaptchaService; import com.orange.ecare.util.RequestUtils; import com.sun.image.codec.jpeg.JPEGCodec; import com.sun.image.codec.jpeg.JPEGImageEncoder; public class CaptchaController extends AbstractController { private Log log = LogFactory.getLog(CaptchaController.class.getName()); //************************* SPRING INJECTED ********************************* private ImageCaptchaService captchaService; public ImageCaptchaService getCaptchaService() {return captchaService;} public void setCaptchaService(ImageCaptchaService captchaService) {this.captchaService = captchaService;} //************************* SPRING INJECTED ********************************* public CaptchaController(){ System.setProperty("java.awt.headless", "true"); } protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) throws Exception { log.debug("Captcha requested by : " + RequestUtils.getRemoteAddr(request)); byte[] captchaChallengeAsJpeg = null; // the output stream to render the captcha image as jpeg into ByteArrayOutputStream jpegOutputStream = new ByteArrayOutputStream(); try { // get the session id that will identify the generated captcha. //the same id must be used to validate the response, the session id is a good candidate! String captchaId = request.getSession().getId(); // call the ImageCaptchaService getChallenge method BufferedImage challenge = ((ImageCaptchaService)getCaptchaService()).getImageChallengeForID(captchaId, request.getLocale()); // a jpeg encoder JPEGImageEncoder jpegEncoder = JPEGCodec.createJPEGEncoder(jpegOutputStream); jpegEncoder.encode(challenge); } catch (IllegalArgumentException e) { response.sendError(HttpServletResponse.SC_NOT_FOUND); return null; } catch (CaptchaServiceException e) { response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); return null; } captchaChallengeAsJpeg = jpegOutputStream.toByteArray(); // flush it in the response response.setHeader("Cache-Control", "no-store"); response.setHeader("Pragma", "no-cache"); response.setDateHeader("Expires", 0); //response.setContentType("image/jpeg"); //response.getOutputStream().write(jpegOutputStream); ServletOutputStream responseOutputStream = response.getOutputStream(); responseOutputStream.write(captchaChallengeAsJpeg); responseOutputStream.flush(); responseOutputStream.close(); return null; } }

the jsp

<%@ taglib prefix="form" uri="/WEB-INF/spring-form.tld" %> <%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %> <%@ taglib uri="/WEB-INF/c-1_0.tld" prefix="c" %> <div class="copy col_other col_width2"> <div id="captchaApp"><img id="captchaImage" src="<c:out value="${requestScope.baseUrl}"/>/pub/captcha" width="300" height="80" alt="captcha" /></div> </div> <div class="copy col_other col_width3 orange_text vspaced10"><spring:message code="vouchers.voucher.title.why.captcha"/></div> <div class="copy col_other col_width5">&nbsp;</div> <div class="copy col_other col_width2"> <div class="entry"> <label id="captchaLongLabel" for="captcha" accesskey="c" class="entry_title"><spring:message code="vouchers.voucher.label.captcha"/></label> </div> </div> <div class="copy col_other col_width3"> <div class="entry"> <input type="text" id="captcha" name="captcha" class="entry_field" value="" tabindex="70" /> <c:if test="${not empty captchaError}"> <div id="captchaError"> </c:if> <c:if test="${empty captchaError}"> <div id="captchaError" style="display:none;"> </c:if> <div class="errorMarker">&nbsp;</div> <div class="error"> <p> <img id="warning" src="/ecare/images/warning_symbol_small.gif" alt="warning symbol" width="28" height="30" align="left"/> <spring:message code="vouchers.voucher.error.captcha"/> </p> </div> </div> </div> </div>

the controller

package com.orange.ecare.spring.mvc.controllers.jsp.vouchers; import java.util.Map; 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.web.servlet.ModelAndView; import com.octo.captcha.service.image.ImageCaptchaService; import com.orange.ecare.spring.misc.CountingBean; import com.orange.ecare.spring.mvc.controllers.abstracts.AbstractRestfulController; import com.orange.ecare.spring.mvc.controllers.tokens.RequestTokens; import com.orange.ecare.util.RequestUtils; import com.orange.ecare.webservices.webmethods.clients.accountStatus.AccountStatusClient; import com.orange.ecare.webservices.webmethods.clients.redeemVoucher.RedeemVoucherClient; public class Vouchers extends AbstractRestfulController { private Log log = LogFactory.getLog(Vouchers.class.getName()); //******************** Spring Injected *************** private AccountStatusClient accountStatusClient; private RedeemVoucherClient redeemVoucherClient; private ImageCaptchaService captchaService; private CountingBean captchaAttempts; private CountingBean voucherAttempts; private RequestTokens requestTokens; public AccountStatusClient getAccountStatusClient() {return accountStatusClient;} public void setAccountStatusClient(AccountStatusClient accountStatusClient) {this.accountStatusClient = accountStatusClient;} public RedeemVoucherClient getRedeemVoucherClient() {return redeemVoucherClient;} public void setRedeemVoucherClient(RedeemVoucherClient redeemVoucherClient) {this.redeemVoucherClient = redeemVoucherClient;} public RequestTokens getRequestTokens() {return requestTokens;} public void setRequestTokens(RequestTokens requestTokens) {this.requestTokens = requestTokens;} public CountingBean getCaptchaAttempts() {return captchaAttempts;} public CountingBean getVoucherAttempts() {return voucherAttempts;} public void setVoucherAttempts(CountingBean voucherAttempts) {this.voucherAttempts = voucherAttempts;} public void setCaptchaAttempts(CountingBean captchaAttempts) {this.captchaAttempts = captchaAttempts;} public ImageCaptchaService getCaptchaService() {return captchaService;} public void setCaptchaService(ImageCaptchaService captchaService) {this.captchaService = captchaService;} //**************************************************** //********************* validation methods *********** //**************************************************** protected boolean isCaptchaValid(HttpServletRequest req,String answer) throws Exception { Boolean isResponseCorrect = getCaptchaService().validateResponseForID(req.getSession().getId(),answer); return isResponseCorrect.booleanValue(); } protected boolean isMsisdnValid(String msisdn) throws Exception { return getAccountStatusClient().isValidMSISDN(msisdn); } protected boolean isVoucherValid(String msisdn, String voucher,Map model) throws Exception { return getRedeemVoucherClient().processVoucher(msisdn, voucher); } //**************************************************** //**************************************************** //**************************************************** protected ModelAndView doPost(HttpServletRequest request, HttpServletResponse response, Map model) throws Exception { log.debug("user submitted a voucher redemption request form"); //first check for double clicked submission using the token bean if (!getRequestTokens().isTokenValid(request)) { log.debug("user tried to redeem the same voucher twice"); return new ModelAndView("vouchers/badToken",model); } //Firstly check to see if the captcha challenge was good String canswer = request.getParameter("captcha"); if (canswer==null || (!isCaptchaValid(request,canswer))) { log.debug("user failed capcha they entered " + canswer); //make tell the JSP that captcha failed model.put("captchaError",new Boolean(true)); //increment the number of captcha attempts getCaptchaAttempts().incAttempts(request); //handle max captcha attempts if (getCaptchaAttempts().isMaxAttempts(request)) { log.warn("REPEATEDELY_FAILED_VOUCHER_CAPTCHAS (" + RequestUtils.getRemoteAddr(request) + ")"); return new ModelAndView("exception/maxCaptcha",model); } else { return new ModelAndView("vouchers/vouchers",model); } } //now check that the MSISDN is valid String msisdn = request.getParameter("msisdn"); if (msisdn==null || (!isMsisdnValid(msisdn))) { log.debug("user entered an invalid msisdn : " + msisdn); model.put("msisdnError",new Boolean(true)); return new ModelAndView("vouchers/vouchers",model); } //finally, attempt to redeem the voucher String voucher = request.getParameter("voucherNumber"); if (voucher==null || (!isVoucherValid(msisdn,voucher,model))) { log.debug("user entered an invalid voucher : " + voucher); model.put("voucherError",new Boolean(true)); getVoucherAttempts().incAttempts(request); if (getVoucherAttempts().isMaxAttempts(request)) { log.warn("REPEATEDLY_FAILED_VOUCHER_REDEMPTION (" + RequestUtils.getRemoteAddr(request) + ")"); return new ModelAndView("exception/maxCaptcha",model); } else { return new ModelAndView("vouchers/vouchers",model); } } //redemption succeeded return new ModelAndView("vouchers/voucher_accepted",model); } protected ModelAndView doGet(HttpServletRequest request, HttpServletResponse response, Map model) throws Exception { log.debug("User requested the displaying of the voucher redemption page"); //check to see if the user has reached the maximum captcha attempts if (getCaptchaAttempts().isMaxAttempts(request)) { log.warn("user has requested the voucher topup page to be displayed but has already had the maximum number of captcha attempts for this session"); return new ModelAndView("exception/maxCaptcha",model); } if (getVoucherAttempts().isMaxAttempts(request)) { log.warn("user has requested the voucher topup page to be displayed but has already had the maximum number of voucher attempts for this session"); return new ModelAndView("exception/maxVoucher",model); } //reset the request token getRequestTokens().resetToken(request); return new ModelAndView("vouchers/vouchers",model); } }