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) {

  ....

}

相關文章
相關標籤/搜索