jcaptcha组件小小改造解决Invalid ID, could not validate unexisting or already validated captcha

jcaptcha是一款很好的java实现的验证码组件,官方地址:http://jcaptcha.sourceforge.net/
在使用jcaptcha过程中,我相信很多人在用ajax校验验证码的时候都遇到过下面这样的异常:

Invalid ID, could not validate unexisting or already validated captcha

其实分析jcaptcha源码不难得知,这个异常是因为AbstractCaptchaService中的validateResponseForID方法逻辑在捣乱,看看源码:


其中有句this.store.removeCaptcha(ID);,就是这句代码在捣乱。这句代码的意思就是说,不管什么时候,一档执行了validateResponseForID方法,就会把原来的那个session从store当中移除,那么这样,如果你采用的是ajax提交校验的话,验证码生成逻辑没有重新执行,就会报上面的Invalid ID异常,如果是校验失败就重新刷新页面重新生成应该就问题,没有验证是不是这样,道理就是这么个道理了……
那么为了满足ajax校验,我们做点稍微的改造:
首先我们如果采用的GenericManageableCaptchaService作为CaptchaService实现类,我就自定义一个Service来继承GenericManageableCaptchaService,代码如下:

package com.somnus.support.captcha;

import com.octo.captcha.engine.CaptchaEngine;
import com.octo.captcha.service.CaptchaServiceException;
import com.octo.captcha.service.multitype.GenericManageableCaptchaService;

/** 
 * @Description: TODO
 * @author Somnus
 * @date 2015年11月24日 下午1:21:50 
 * @version V1.0 
 */
public class CustomGenericManageableCaptchaService extends GenericManageableCaptchaService{

    /**
     * @param captchaEngine
     * @param minGuarantedStorageDelayInSeconds
     * @param maxCaptchaStoreSize
     */
    public CustomGenericManageableCaptchaService(CaptchaEngine captchaEngine, int minGuarantedStorageDelayInSeconds,
            int maxCaptchaStoreSize) {
        super(captchaEngine, minGuarantedStorageDelayInSeconds, maxCaptchaStoreSize);
        // TODO Auto-generated constructor stub
    }
    /**
     * 修改验证码校验逻辑,默认的是执行了该方法后,就把sessionid从store当中移除<br/>
     * 然而在ajax校验的时候,如果第一次验证失败,第二次还得重新刷新验证码,这种逻辑不合理<br/>
     * 现在修改逻辑,只有校验通过以后,才移除sessionid。 Method Name:validateResponseForID .
     * 
     * @param ID
     * @param response
     * @return
     * @throws CaptchaServiceException
     *             the return type:Boolean
     */
    @Override
    public Boolean validateResponseForID(String ID, Object response)
            throws CaptchaServiceException {
        if (!this.store.hasCaptcha(ID)) {
            throw new CaptchaServiceException(
                    "Invalid ID, could not validate unexisting or already validated captcha");
        }
        Boolean valid = this.store.getCaptcha(ID).validateResponse(response);
        //源码的这一句是没被注释的,这里我们注释掉,在下面暴露一个方法给我们自己来移除sessionId
        //this.store.removeCaptcha(ID);
        return valid;
    }
     
    /**
     * 移除session绑定的验证码信息.
     * Method Name:removeCaptcha .
     * @param sessionId
     * the return type:void
     */
    public void removeCaptcha(String sessionId){
        if(sessionId!=null && this.store.hasCaptcha(sessionId)){
            this.store.removeCaptcha(sessionId);
        }
    }

}

从代码中我们可以看到两个改造:
1、重写了validateResponseForID方法,只是注释了一行代码;
2、增加了一个方法removeCaptcha,用来让我们手工移除session对应的验证码信息

然后就把bean对应的实现类指定到我们的自定义实现上,如下:

<bean id="captchaService" class="com.somnus.support.captcha.CustomGenericManageableCaptchaService">
    <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>
    <constructor-arg index="3"><value>75000</value></constructor-arg>
</bean>

最后就是在你的业务逻辑里面手动调用removeCapthca()方法了,例如:

jcaptcha组件小小改造解决Invalid ID, could not validate unexisting or already validated captcha_第1张图片



你可能感兴趣的:(id,validate,JCAPTCHA,Invalid,unexisting)