一、前言
有时我们在web应用登录页可能需要进行验证码校验,那么我们就可以使用Kaptcha来生成自定义的验证码,然后以base64的形式返回给前端,前端再在登陆页面展示出来就可以了。
二、实现
1.首先在springboot项目中引入相关的Kapcha依赖。
<dependency>
<groupId>com.github.penggle</groupId>
<artifactId>kaptcha</artifactId>
<version>2.3.2</version>
</dependency>
2.接下来需要进行相应的Kaptcha配置,代码如下。
import java.util.Properties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.google.code.kaptcha.impl.DefaultKaptcha;
import com.google.code.kaptcha.util.Config;
@Configuration
public class KaptchaConfig {
@Bean
public DefaultKaptcha producer() {
Properties properties = new Properties();
properties.put("kaptcha.border", "no"); // 图片边框
properties.put("kaptcha.textproducer.font.color", "black"); // 字体颜色
properties.put("kaptcha.background.clear.from", "black"); //背景颜色渐变色开始色 rgb或者Color中定义的
properties.put("kaptcha.background.clear.to", "green"); //背景颜色渐变色结束色 rgb或者Color中定义的
properties.put("kaptcha.textproducer.char.space", "10"); //验证码文本字符间距 默认为2
properties.put("kaptcha.textproducer.char.length","4"); // 验证码长度
properties.put("kaptcha.image.height","34"); // 图片高
properties.put("kaptcha.image.width", "110"); //图片宽
properties.put("kaptcha.textproducer.font.size","25"); // 字体大小
properties.put("kaptcha.word.impl","com.google.code.kaptcha.text.impl.DefaultWordRenderer"); //文字渲染器
// 字体
properties.put("kaptcha.textproducer.font.names", "宋体,楷体,微软雅黑"); //字体类型
/**
* 图片样式的实现类,默认WaterRipple(水纹),还有下面2种可选
* 鱼眼com.google.code.kaptcha.impl.FishEyeGimpy 阴影com.google.code.kaptcha.impl.ShadowGimpy
*/
properties.put("kaptcha.obscurificator.impl", "com.google.code.kaptcha.impl.WaterRipple"); //字体类型
properties.put("kaptcha.background.impl", "com.google.code.kaptcha.impl.DefaultBackground"); //背景图片实现类,默认DefaultBackground,也只有这一个默认实现类
properties.put("kaptcha.noise.impl","com.google.code.kaptcha.impl.NoNoise"); //文字干扰实现类,默认DefaultNoise,还可以选择com.google.code.kaptcha.impl.NoNoise没有干扰线的实现类
Config config = new Config(properties);
DefaultKaptcha defaultKaptcha = new DefaultKaptcha();
defaultKaptcha.setConfig(config);
return defaultKaptcha;
}
}
这些配置可以根据需要自定义配置。
3.配置好以后,我们在Controller层定义一个接口,返回base64给前端调用,代码如下:
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Map;
import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.google.code.kaptcha.Producer;
import com.suntree.commons.ApiResult;
import com.suntree.service.KaptchaService;
import sun.misc.BASE64Encoder;
@RestController
@RequestMapping("/token")
public class KaptchaController {
@Autowired
private KaptchaService kaptchaService;
@Autowired
private Producer producer;
@PostMapping("/kaptcha")
public ApiResult captcha(HttpServletResponse response) throws ServletException, IOException {
// 生成文字验证码
String text = producer.createText();
// 生成图片验证码
ByteArrayOutputStream outputStream = null;
BufferedImage image = producer.createImage(text);
outputStream = new ByteArrayOutputStream();
ImageIO.write(image, "jpg", outputStream);
// 对字节数组Base64编码
BASE64Encoder encoder = new BASE64Encoder();
// 生成captcha的token
Map<String, Object> map = (Map<String, Object>) kaptchaService.createToken(text).getData();
map.put("img", encoder.encode(outputStream.toByteArray()));
ApiResult result=new ApiResult();
return result.success(map);
}
}
4.最后我们可以把base64给前端调用,以登录界面为例,Html代码如下:
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>登陆界面</title>
<link rel="stylesheet" href="../css/login.css">
<style type="text/css">
#login_error{
color: #f00;
font-size: 15px;
height: 24px;
margin-left: 48px;
visibility: hidden;
}
input[type="button"] {
margin-top: 25px;
margin: 0 auto;
display: block;
border-radius: 3px;
border: 1px solid #c8cccf;
width: 240px;
height: 35px;
background: #357eb8;
color: #bcedff;
font-weight: bold;
font-size: 16px;
outline: 0;
}
input[type="button"]:hover {
background: #0e62a3;
cursor: pointer;
}
#captchaimg{
display: inline-block;
margin-left: 45px;
vertical-align:middle;
margin-bottom: 10px;
}
#kaptcha{
text-decoration: none;
}
</style>
<script th:src="@{../js/jquery-3.1.1.js}"></script>
<script type="text/javascript">
</script>
</head>
<body>
<div class="container">
<!-- 导航 -->
<div class="nav">
<ul>
<li><a href="#">帮助</a></li>
<li><a href="#">案例</a></li>
<li><a href="#">产品</a></li>
<li><a href="#">首页</a></li>
</ul>
</div>
<!-- 主体内容 (登陆界面)-->
<div class="main">
<!-- 左侧信息栏 -->
<div class="sideleft">
<h1>海量品牌 信息共享</h1>
<h4>数据结合商业 让大数据发挥大价值</h4>
<p>精准营销、数据化管理,提升管理水平。</p>
<p>打造线上线下数字一体化。</p>
<p>双选平台,建立工厂与经销商双向选择平台。</p>
<p>服务市场,塑造经销商信用等级,为其提供相应的金融服务。</p>
<br><br><br>
</div>
<!-- 右侧登陆界面 -->
<div class="sideright">
<div class="index">
<form id="form1" action="" method="post" enctype="application/json">
<p class="headline">用户登陆</p>
<span id="login_error">登陆 </span>
<p class="astyle">账号:</p>
<input id="accNum" type="text" name="accNum" placeholder="请输入账号" />
<p class="astyle">密码:</p>
<input id="passwd" type="password" name="passwd" placeholder="请输入密码" style="width:240px;height:35px;margin:0 auto;display:block;border-radius:3px;border:1px solid #808080;" />
<p class="astyle">验证码:</p>
<input id="code" type="text" name="code" placeholder="请输入验证码" /><br>
<img id="captchaimg" alt="如果看不清楚,请单击图片刷新!" class="pointer" src=""> <a id="kaptcha" href="" onclick="refreshKaptcha()">看不清?换一张</a>
<br>
<input id="login" type="button" value="登陆" name="login" >
<br>
<p class="bstyle"><input type="checkbox" name="rempas" /> 记住密码</p>
<p class="cstyle">忘记密码</p>
<br><br>
<p class="cstyle">没有账号?<a href="zhuce.html">立即注册</a></p>
</form>
</div>
</div>
</div>
</div>
<script src="../js/login.js"></script>
</body>
</html>
JS代码如下:
在这里插入代码片
```onload=function(){
var token;
var expireTm;
$.ajax({
type:'POST',
url:'/token/kaptcha/',
dataType:'json',
data: '',
// data: $("#form1").serialize(),
success:function (result) {
if (result.code == 1){
$("#captchaimg").attr('src','data:image/jpeg;base64,'+result.data.img);
login(result);
}else{
alert(result.info);
//callback && callback(false);
}
},
error:function (result) {
alert("获取失败");
}
});
}
5.接着我们可以定义WebMvcConfig,实现WebMvcConfigurer类,代码如下:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/user/login").setViewName("/login");
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
//registry.addInterceptor(accessInterceptor);
}
}
这里是把前后端代码都写在springboot中了。
6.在浏览器上访问就可以看到最终展示效果了,如下图: