概要
- Spring Boot で kaptcha を使う
- 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>
完成した画面
こんな感じで画像が表示される。
参照
ここまでの全ソースコードは、以下のリポジトリに置いてあります。