2
2

More than 5 years have passed since last update.

Spring Bootを使ってXMLなしでkaptchaを使う

Posted at

概要

  • Spring Bootkaptcha を使う
  • kaptchaは通常XML設定ファイルを使うけど、せっかくSpring Bootを使うのでXMLファイルなしでkaptchaを使いたい
  • アプリケーションはGroovy + Gradleで

build.gradle

ポイントは、kaptchaがMavenリポジトリにないので、jarをlib以下に入れて依存関係に追加しているとこ。lib以下の全jarを対象にしているのは手抜き。

(省略)

dependencies {
  compile fileTree(dir: 'lib', include: '*.jar')
}

(省略)

Bean定義のクラスを作る

kaptchaの例だと、web.xmlでservletに kaptcha.jpg をマッピングしているのを、 @Configuration で指定したクラスで設定する。

@Configuration
public class AppConfig {
  @Bean
  public ServletRegistrationBean kaptcha() {
   new ServletRegistrationBean(new KaptchaServlet(), "/kaptcha.jpg")
  }

}

入力データクラスを作る

画面から受け取るのは、kaptchaの文字列だけ。
かつ、Groovyなのでsetter/getterも不要。ただし、属性を def で宣言しちゃうと、Object型になって実行時にエラーになっちゃう。

public class KaptchaFormData {
    @NotNull
    @Size(min = 5, message = "入力した文字が短すぎます")
    String kaptcha
}

kaptcha解決のサービスクラスを作る

といっても、文字列同士を大文字/小文字関係なく比較するだけ。

@Service
public class SolveKaptchaService {

  public boolean solve(String expected, String actual) {
    actual.equalsIgnoreCase(expected)
  }
}

Controllerクラスを作る

kaptchaActionメソッドでリクエストを受ける。入力値が短いとか、入力されてない、のはデータクラスに指定したアノテーション通りにチェック。

kaptchaActionメソッドは、HttpSessionオブジェクトも受け取るようになっていて、セッションからkaptchaの正解文字列を取得してくる。

あとは、入力文字列と正解文字列をServiceクラスに渡して完了。

@Controller
public class KaptchaController {

  @Autowired
  SolveKaptchaService solveKaptcha

    @ModelAttribute("kaptchaFormData")
    KaptchaFormData setUp() {
        new KaptchaFormData()
    }

  @RequestMapping(value = "/", method = RequestMethod.GET)
  public String kaptcha() {
    "index"
  }

  @RequestMapping(value = "/", method = RequestMethod.POST)
  public String kaptchaAction(@Validated KaptchaFormData kaptchaFormData, BindingResult bindingResult, 
      Model model, HttpSession session) {

      if (bindingResult.hasErrors()) {
          return "index"
      }

      def expectedKaptcha = (String)session.getAttribute(Constants.KAPTCHA_SESSION_KEY)

      if (!solveKaptcha.solve(expectedKaptcha, kaptchaFormData.kaptcha)) {
        model.addAttribute("exception", new Exception("入力した文字が画像と違います。"))
        return "index"
      }

    "success"
  }
}

画面

画面は、Thymeleafを使ってテンプレート化してる。

ポイントになるのは、kaptchaをクリックするたびに画像が変更されるようにしているとこ。Thymeleafの th:inline"javascript" を使ってるとこ。

<!DOCTYPE html>
<html xmlns:th="http:///www.thymeleaf.org">
<head>
  <meta charset="UTF-8" />
  <title>kaptcha Login</title>
  <script th:src="@{/jquery-1.11.1.min.js}" />
</head>
<body>
<h1>ログイン</h1>
<form name="kForm" method="post" th:action="@{/}" th:object="${kaptchaFormData}">
  <div>
    <span th:if="${#fields.hasErrors('kaptcha')}" th:errors="*{kaptcha}" style="color: red;">error!</span>
    <span th:if="${exception != null}" th:text="${exception.message}" style="color: red;">error!</span>
  </div>
  <div><img th:src="@{/kaptcha.jpg}" width="200" id="kaptchaImage" /></div>
  <script th:inline="javascript">
    var kaptchaUrl = /*[[@{/kaptcha.jpg}]]*/ "/kaptcha.jpg";
    $(function(){
      $('#kaptchaImage').on('click', function() {
        $(this).attr('src', kaptchaUrl + '?' + Math.floor(Math.random()*100) );
      })
    });
  </script>
  <div>
    <input type="text" name="kaptcha" value="" th:field="*{kaptcha}" />
  </div>
  <div>
    <button id="loginButton" onCLick="document.kForm.submit();">ログイン</button>
  </div>
</form>
</body>
</html>

完成した画面

こんな感じで画像が表示される。

kobito.1417687627.261864.png

参照

ここまでの全ソースコードは、以下のリポジトリに置いてあります。
* SpringBootCaptcha

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2