アカウント取得とかで出るゆらゆら文字

ほら、よくHotmailとかでアカウントを取ろうとしてら、
ゆらゆらとした、ゆがんだ文字のGIF画像が出るじゃないですか。

「表示された文字を入力してください」

ってこんな感じ。
機械的にアカウントを取得させないのが目的なんでしょうけど、
この仕組みってなんて呼べばいいんでしょうか?


ついでにJavaでこの「ゆらゆら文字」が生成できるライブラリとかありましたら、
教えてくださいな。

WebWorkのIoCコンテナ

WebWork 2(正確にはXWork)にも独自のIoCコンテナがありますが、
S2やSpringと一緒に使うときは、コンポーネントの管理をDIコンテナに一元化したほうがいいと思います。
S2の場合、sessionやrequestスコープが用意されているので、移行は簡単だと思います。これでWebWork側ではイネーブラインターフェイスがいらなくなるはずです。


今のところ手元で試したのはそこまでですが、さらに、WebWork側のInterceptorもS2の管理下におければ、WebWork側のInterceptorにもインジェクションできるようになるので、かなり強力になりますね。

jcaptchaの使い方

動いた!
Strutsのmoduleが含めれていますが、こいつが参考になりました。
jcaptcha自体はかなりDI指向な作りになっていますので、
DIコンテナで使うのは、かなり簡単みたいです。
登録したサービスはこのクラスのみ。


  CAPTCHAクラス

以下は、ゆらゆら画像の出力処理。
WebWorkなんで、ServletActionContextをつかっていますが、
Strutsなんかでも基本は同じハズ。
CaptchaModuleConfigHelper.getId(request)で、セッションの中に
トークンのような物が作られるみたい。

HttpServletRequest request = ServletActionContext.getRequest(); 
    HttpServletResponse response = ServletActionContext.getResponse();
String captchaID = CaptchaModuleConfigHelper.getId(request);
byte[] captchaChallengeAsJpeg = null;
ByteArrayOutputStream jpegOutputStream = new ByteArrayOutputStream();
try {
  BufferedImage challenge = imageCaptchaService.getImageChallengeForID(captchaID,
      request.getLocale());
  JPEGImageEncoder jpegEncoder = JPEGCodec
      .createJPEGEncoder(jpegOutputStream);
  jpegEncoder.encode(challenge);
} catch (IllegalArgumentException e) {
  if (log.isWarnEnabled()) {
    log.warn("There was a try from "
        + request.getRemoteAddr()
        + " to render an URL without ID"
        + " or with a too long one");
    response.sendError(HttpServletResponse.SC_NOT_FOUND);
    log.error("should never pass here!");
    return ERROR;
  }
} catch (CaptchaServiceException e) {
  log.warn("Error trying to generate a captcha and "
      + "render its challenge as JPEG", e);
  response.sendError(HttpServletResponse.SC_NOT_FOUND);
  return ERROR;
}
captchaChallengeAsJpeg = jpegOutputStream.toByteArray();
response.setHeader("Cache-Control", "no-store");
response.setHeader("Pragma", "no-cache");
response.setDateHeader("Expires", 0);
response.setContentType("image/jpeg");
ServletOutputStream responseOutputStream = response
		.getOutputStream();
responseOutputStream.write(captchaChallengeAsJpeg);
responseOutputStream.flush();
responseOutputStream.close();
return null;

入力された文字のチェックは以下のような感じ。
captchaResponseが入力された文字の場合、以下のようなコードになります。
1度でも認証に失敗するとトークンがなくなって、
2回目以降はエラーになります。

HttpServletRequest request = ServletActionContext.getRequest(); 
    HttpServletResponse response = ServletActionContext.getResponse();
String captchaID = CaptchaModuleConfigHelper.getId(request);

try {
  Boolean challengeObject = imageCaptchaService.validateResponseForID(captchaID, captchaResponse);
  boolean validateChaptchaResponceForID = challengeObject.booleanValue();
  return validateChaptchaResponceForID;
} catch (CaptchaServiceException e) {
  return false;
}

ServletFilterは結局使ってなくて、注意点としてはEHCacheのJarが必要なとこ。

コンポーネント指向

メール、Wiki、CHAPTCHAなど何らかのサービスを提供するコンポーネントが、
DIに対応していくことですることで、今後、再利用性の高いライブラリが
続々とでてくるように思えます。


コンフィグレーションと、使用したい場所へのインジェクションが
簡単にできるようになるのがDI対応コンポーネントの強みでしょうね。