jcaptcha组件小小改造解决Invalid ID, could not validate une

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

Invalid ID, could not validate unexisting or already validated captchaajax

其实分析jcaptcha源码不可贵知,这个异常是由于AbstractCaptchaService中的validateResponseForID方法逻辑在捣乱,看看源码:session

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);
    this.store.removeCaptcha(ID);
    return valid;
  }

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

public class CustomGenericManageableCaptchaService extends
		GenericManageableCaptchaService {

	/**
	 * The constructor method of class CustomManageableCaptchaService.java .
	 * 
	 * @param captchaEngine
	 * @param minGuarantedStorageDelayInSeconds
	 * @param maxCaptchaStoreSize
	 * @param captchaStoreLoadBeforeGarbageCollection
	 */
	public CustomGenericManageableCaptchaService(CaptchaEngine captchaEngine,
			int minGuarantedStorageDelayInSeconds, int maxCaptchaStoreSize,
			int captchaStoreLoadBeforeGarbageCollection) {
		super(captchaEngine, minGuarantedStorageDelayInSeconds,
				maxCaptchaStoreSize, captchaStoreLoadBeforeGarbageCollection);
	}

	/**
	 * The constructor method of class CustomManageableCaptchaService.java .
	 * 
	 * @param captchaStore
	 * @param captchaEngine
	 * @param minGuarantedStorageDelayInSeconds
	 * @param maxCaptchaStoreSize
	 * @param captchaStoreLoadBeforeGarbageCollection
	 */
	public CustomGenericManageableCaptchaService(CaptchaStore captchaStore,
			CaptchaEngine captchaEngine, int minGuarantedStorageDelayInSeconds,
			int maxCaptchaStoreSize, int captchaStoreLoadBeforeGarbageCollection) {
		super(captchaStore, captchaEngine, minGuarantedStorageDelayInSeconds,
				maxCaptchaStoreSize, captchaStoreLoadBeforeGarbageCollection);
	}

	/**
	 * 修改验证码校验逻辑,默认的是执行了该方法后,就把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);
		}
	}
}

从代码中咱们能够看到两个改造:
一、重写了validateResponseForID方法,只是注释了一行代码;
二、增长了一个方法removeCaptcha,用来让咱们手工移除session对应的验证码信息
this

而后就把bean对应的实现类指定到咱们的自定义实现上,以下:spa

<bean id="captchaService" class="com.cmcc.ict.iplanning.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()方法了,例如:.net

try {code

  currentUser.login(token);继承

  ....token

  //成功之后移除验证码信息

  captchaService.removeCaptcha(sessionId);

} catch (UnknownAccountException uae) {

  ....

} catch (IncorrectCredentialsException ice) {

  ....

} catch (LockedAccountException lae) {

  ....

} catch (ExcessiveAttemptsException eae) {

  ....

} catch (AuthenticationException ae) {

  ....

}

相关文章
相关标签/搜索