一、引入依赖
<dependency>
<groupId>com.github.penggle</groupId>
<artifactId>kaptcha</artifactId>
<version>2.3.2</version>
</dependency>
三、配置类KaptchaConfig
package com.jinv.studentinfo.config;
import com.google.code.kaptcha.impl.DefaultKaptcha;
import com.google.code.kaptcha.util.Config;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
import java.util.Properties;
@Component
public class KaptchaConfig {
@Bean
public DefaultKaptcha getDefaultKaptcha() {
com.google.code.kaptcha.impl.DefaultKaptcha defaultKaptcha = new com.google.code.kaptcha.impl.DefaultKaptcha();
Properties properties = new Properties();
// 图片边框
properties.setProperty("kaptcha.border", "no");
// 边框颜色
properties.setProperty("kaptcha.border.color", "black");
//边框厚度
properties.setProperty("kaptcha.border.thickness", "1");
// 图片宽
properties.setProperty("kaptcha.image.width", "120");
// 图片高
properties.setProperty("kaptcha.image.height", "40");
//图片实现类
properties.setProperty("kaptcha.producer.impl", "com.google.code.kaptcha.impl.DefaultKaptcha");
//文本实现类
properties.setProperty("kaptcha.textproducer.impl", "com.google.code.kaptcha.text.impl.DefaultTextCreator");
//文本集合,验证码值从此集合中获取
properties.setProperty("kaptcha.textproducer.char.string", "01234567890");
//验证码长度
properties.setProperty("kaptcha.textproducer.char.length", "4");
//字体
properties.setProperty("kaptcha.textproducer.font.names", "宋体");
//字体颜色
properties.setProperty("kaptcha.textproducer.font.color", "black");
//文字间隔
properties.setProperty("kaptcha.textproducer.char.space", "5");
//干扰实现类
properties.setProperty("kaptcha.noise.impl", "com.google.code.kaptcha.impl.DefaultNoise");
//干扰颜色
properties.setProperty("kaptcha.noise.color", "blue");
//干扰图片样式
properties.setProperty("kaptcha.obscurificator.impl", "com.google.code.kaptcha.impl.WaterRipple");
//背景实现类
properties.setProperty("kaptcha.background.impl", "com.google.code.kaptcha.impl.DefaultBackground");
//背景颜色渐变,结束颜色
properties.setProperty("kaptcha.background.clear.to", "white");
//文字渲染器
properties.setProperty("kaptcha.word.impl", "com.google.code.kaptcha.text.impl.DefaultWordRenderer");
Config config = new Config(properties);
defaultKaptcha.setConfig(config);
return defaultKaptcha;
}
}
四、kaptchaUtils工具类接收web层的request和response参数,生成验证码
package com.jinv.studentinfo.utils;
import com.google.code.kaptcha.impl.DefaultKaptcha;
import javax.imageio.ImageIO;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.image.BufferedImage;
public class KaptchaUtils {
/**
* 生成验证码图片
* @param request 设置session
* @param response 转成图片
* @param captchaProducer 生成图片方法类
* @param validateSessionKey session名称
* @throws Exception
*/
public static void validateCode(HttpServletRequest request, HttpServletResponse response, DefaultKaptcha captchaProducer, String validateSessionKey) throws Exception{
// Set to expire far in the past.
response.setDateHeader("Expires", 0);
// Set standard HTTP/1.1 no-cache headers.
response.setHeader("Cache-Control", "no-store, no-cache, must-revalidate");
// Set IE extended HTTP/1.1 no-cache headers (use addHeader).
response.addHeader("Cache-Control", "post-check=0, pre-check=0");
// Set standard HTTP/1.0 no-cache header.
response.setHeader("Pragma", "no-cache");
// return a jpeg
response.setContentType("image/jpeg");
// create the text for the image
String capText = captchaProducer.createText();
// store the text in the session
request.getSession().setAttribute(validateSessionKey, capText);
// create the image with the text
BufferedImage bi = captchaProducer.createImage(capText);
ServletOutputStream out = response.getOutputStream();
// write the data out
ImageIO.write(bi, "jpg", out);
try {
out.flush();
} finally {
out.close();
}
}
}
五、web层(这里用的@Resource其实用@Autowired也是可以的)
详细区请看@Resource和@Autowired的区别篇
https://blog.csdn.net/SuchASilly/article/details/106064965
@Resource
private DefaultKaptcha kaptchaProducer;
/**
* 登录校验表单以及验证码
* @param request
* @param validateCode
*/
@PostMapping("/login")
public void login(HttpServletRequest request,@RequestParam("validateCode")String validateCode){
}
/**
* 登录验证码SessionKey
*/
public static final String LOGIN_VALIDATE_CODE = "login_validate_code";
/**
* 登录验证码图片
*/
@GetMapping("/loginValidateCode")
public void loginValidateCode(HttpServletRequest request,HttpServletResponse response) throws Exception {
KaptchaUtils.validateCode(request,response,kaptchaProducer,LOGIN_VALIDATE_CODE);
}
/**
* 验证登录验证码
* @param request
* @param validateCode
* @return
*/
@PostMapping("/checkLoginValidateCode")
public HashMap checkLoginValidateCode(HttpServletRequest request,@RequestParam("validateCode")String validateCode){
String loginValidateCode = request.getSession().getAttribute(LOGIN_VALIDATE_CODE).toString();
HashMap<String,Object> map = new HashMap<>();
if (validateCode==null){
map.put("status",false);//验证失败
}else if (validateCode.equals(loginValidateCode)){
map.put("status",true);//验证成功
}else {
map.put("status",false);//验证失败
}
map.put("code",200);
return map;
}
六、login.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.w3.org/1999/xhtml">
<head>
<title>登录页面</title>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><!--自适应-->
<link rel="stylesheet" href="../static/css/bootstrap.min.css" th:href="@{/css/bootstrap.min.css}" />
<link rel="stylesheet" href="../static/css/bootstrap-responsive.min.css" th:href="@{/css/bootstrap-responsive.min.css}" />
<link rel="stylesheet" href="../static/css/matrix-login.css" th:href="@{/css/matrix-login.css}" />
<link rel="stylesheet" href="../static/font-awesome/css/font-awesome.css" th:href="@{/font-awesome/css/font-awesome.css}" />
<link rel="stylesheet" href="../static/css/me.css" th:href="@{/css/me.css}" />
<style>
.error{
color: #b96027;
}
</style>
</head>
<body>
<div id="loginbox">
<form id="loginform" class="form-vertical" action="#">
<div class="control-group normal_text"> <h3><img src="../static/img/logo1.png" th:src="@{/img/logo1.png}" alt="Logo" /></h3></div>
<div class="control-group">
<div class="controls">
<div class="main_input_box">
<span class="add-on bg_lg"><i class="icon-user"></i></span>
<input type="text" id="username" name="username" class="form-control" required placeholder="用户名。。。" />
</div>
</div>
</div>
<div class="control-group">
<div class="controls">
<div class="main_input_box">
<span class="add-on bg_ly"><i class="icon-lock"></i></span>
<input type="password" id="password" name="password" class="form-control" required placeholder="密码。。。" />
</div>
</div>
</div>
<div class="control-group">
<div class="controls" style="text-align: center">
<img src="/loginValidateCode" th:src="@{/loginValidateCode}" id="loginValidateCode" name="loginValidateCode"
onclick="uploadLoginValidateCode()" class="m-margin-bottom" alt="">
<input type="text" id="validateCode" name="validateCode" class="form-control" required placeholder="验证码。。。">
<p style="color: #b96027" id="validateCodeError"></p>
</div>
</div>
<div class="form-actions" style="text-align: center">
<button type="submit" id="tea-log-btn" name="submit" class="btn btn-success" >教师登录</button>
<button type="submit" id="stu-log-btn" name="submit" class="btn btn-warning" >学生登录</button>
</div>
</form>
</div>
<script src="../static/js/jquery.min.js" th:src="@{/js/jquery.min.js}"></script>
<script src="../static/js/jquery.validate.js" th:src="@{/js/jquery.validate.js}"></script>
<script src="../static/js/messages_zh.js" th:src="@{/js/messages_zh.js}"></script><!--验证表单-->
<script src="../static/js/matrix.login.js" th:src="@{/js/matrix.login.js}"></script>
<script src="../static/js/me/login.js" th:src="@{/js/me/login.js}"></script>
</body>
</html>
七、login.js(这里有个大坑,如果项目设置了context-path的一定要在url上加上根路径,不然验证码图片更新会失败)
/*验证表单*/
$.validator.setDefaults({
submitHandler: function() {
/*验证码校验*/
checkLoginValidateCode($(this).val());
$("#loginform").submit();
alert("表单提交");
}
});
$().ready(function() {
$("#loginform").validate();
});
function uploadLoginValidateCode() {
/*路径一定要加上项目的跟路径*/
$("#loginValidateCode").attr("src","/studentinfo/loginValidateCode?random="+new Date().getMilliseconds());
}
function checkLoginValidateCode(validateCode) {
var error = $("#validateCode").parent().next();
if (validateCode!=null && validateCode!=''){
$.ajax({
type: "POST",
async: false,
url: "/studentinfo/checkLoginValidateCode?validateCode="+validateCode,
success: function (json) {
if (json!=null && json.code ==200 && json.status !=null){
if (json.status==true){
error.html("验证成功!");
}else if (json.status==false){
error.html("验证失败");
}else {
error.html("验证码过期,请重新输入");
uploadLoginValidateCode();
}
}
return false;
},
error:function(XMLHttpRequest,textStatus,errorThrown){
alert("服务器错误!状态码:"+XMLHttpRequest.status);
// 状态
console.log(XMLHttpRequest.readyState);
// 错误信息
console.log(textStatus);
return false;
}
});
}else{
error.html("请输入验证码!");
}
}
最终效果:
点击验证码可以更换图片
表单提交功能还没做好!因为涉及到springboot2.x+redis+fastjson的技术整合所以会在这几天研究补充。。。