springBoot项目加入验证码kaptcha
1:防止恶意攻击,验证码是每个项目必不可少的。先上我的验证码样式,如图
这个是通过谷歌的kaptcha生成的
2;话不多说,首先导入依赖包
下面的joda-time依赖是第三方日期处理神器,这个帖子有介绍
https://blog.csdn.net/a1102325298/article/details/80408872
3:验证码配置类,这里可以设置验证码的长度,宽度,颜色,字体等
package com.example.common;
import com.google.code.kaptcha.impl.DefaultKaptcha;
import com.google.code.kaptcha.util.Config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.Properties;
/**
-
生成验证码配置
*/
@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.textproducer.char.space”, “6”);
//长度
properties.put(“kaptcha.textproducer.char.length”, “5”);Config config = new Config(properties); DefaultKaptcha defaultKaptcha = new DefaultKaptcha(); defaultKaptcha.setConfig(config); return defaultKaptcha;
}
}
4:由于的我验证码是存在数据库的,创建一个验证码实体类
package com.example.entity;
import java.util.Date;
/**
-
系统验证码
*/
public class VerCodeEntity {private String uuid;
/**- 验证码
/
private String code;
/* - 过期时间
*/
private Date expireTime;
public String getUuid() {
return uuid;
}public void setUuid(String uuid) {
this.uuid = uuid;
}public String getCode() {
return code;
}public void setCode(String code) {
this.code = code;
}public Date getExpireTime() {
return expireTime;
}public void setExpireTime(Date expireTime) {
this.expireTime = expireTime;
}
}
5;验证码控制层,用于返回给前端页面。uuid是前端自己生成,请求时传过来的,登陆时前端把uuid和验证码传过来,和数据库去做比对
package com.example.controller;
import com.example.service.VerCodeService;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.awt.image.BufferedImage;
import java.io.IOException; - 验证码
@Controller
@CrossOrigin
@RequestMapping(value = “/api”)
public class VerCodeController {
@Autowired
private VerCodeService verCodeService;
@ResponseBody
@GetMapping("/verCode")
public void captcha(HttpServletResponse response, String uuid) throws ServletException, IOException {
response.setHeader("Cache-Control", "no-store, no-cache");
response.setContentType("image/jpeg");
//获取图片验证码
BufferedImage image = verCodeService.getCaptcha(uuid);
ServletOutputStream out = response.getOutputStream();
ImageIO.write(image, "jpg", out);
IOUtils.closeQuietly(out);
}
}
6;业务层。生成过程已经在注释中说明
package com.example.service;
import com.example.common.RRException;
import com.example.entity.VerCodeEntity;
import com.example.mapper.VerCodeMapper;
import com.example.utils.DateUtils;
import com.google.code.kaptcha.Producer;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.awt.image.BufferedImage;
import java.util.Date;
/**
-
验证码
*/
@Service
public class VerCodeService {
@Autowired
private Producer producer;@Autowired
private VerCodeMapper verCodeMapper;/**
- 获取图片验证码
*/
public BufferedImage getCaptcha(String uuid) {
if (StringUtils.isBlank(uuid)) {
throw new RRException(“uuid不能为空”);
}
//生成文字验证码
String code = producer.createText();
VerCodeEntity captchaEntity = new VerCodeEntity();
captchaEntity.setUuid(uuid);
captchaEntity.setCode(code);
//5分钟后过期
captchaEntity.setExpireTime(DateUtils.addDateMinutes(new Date(), 5));
verCodeMapper.insertSelective(captchaEntity);
return producer.createImage(code);
}
/**
- 验证码效验
- @param uuid uuid
- @param code 验证码
- @return true:成功 false:失败
/
public boolean validate(String uuid, String code) {
VerCodeEntity captchaEntity = verCodeMapper.selectByPrimaryKey(uuid);
//VerCodeEntity captchaEntity = this.selectOne(new EntityWrapper().eq(“uuid”, uuid));
if (captchaEntity == null) {
return false;
}
//长度为1的数组,批量删除
String[] arr = new String[1];
arr[0]=uuid;
//删除验证码
verCodeMapper.deleteBatch(arr);
// this.deleteById(uuid);
//验证码相等且库里面的时间大于当前时间(5分钟之内)
if (captchaEntity.getCode().equalsIgnoreCase(code) && captchaEntity.getExpireTime().getTime() >= System.currentTimeMillis()) {
return true;
}
return false;
}
}
7;(DateUtils.addDateMinutes(new Date(), 5)用到了,刚才提的日期处理神奇Joda-Time,具体代码如下
/* - 对日期的【分钟】进行加/减
- @param date 日期
- @param minutes 分钟数,负数为减
- @return 加/减几分钟后的日期
*/
public static Date addDateMinutes(Date date, int minutes) {
DateTime dateTime = new DateTime(date);
return dateTime.plusMinutes(minutes).toDate();
}
- 获取图片验证码
8:dao层
package com.example.mapper;
import com.example.entity.VerCodeEntity;
import org.apache.ibatis.annotations.Mapper;
/**
-
验证码
*/
@Mapper
public interface VerCodeMapper {int insertSelective(VerCodeEntity verCodeEntity);
VerCodeEntity selectByPrimaryKey(String uuid);
boolean deleteBatch(String[] uuid);
}
9:sql代码。写的很详细,增删改查都有了,哈哈。验证码登陆以后直接删除,写了一个批量删除,其实用不着批量删。一个简单的删除就可以
<?xml version="1.0" encoding="UTF-8" ?><insert id="insertSelective"
parameterType="com.example.entity.VerCodeEntity">
insert into sys_captcha
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="uuid != null and uuid !=''">
uuid,
</if>
<if test="code != null ">
code,
</if>
expireTime
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="uuid != null and uuid !=''">
#{uuid},
</if>
<if test="code != null and code !=''">
#{code},
</if>
#{expireTime}
</trim>
</insert>
<select id="selectByPrimaryKey"
parameterType="java.lang.String" resultMap="VerCodeMap">
select
*
from sys_captcha
where uuid = #{uuid}
</select>
<resultMap type="com.example.entity.VerCodeEntity" id="VerCodeMap">
<result property="uuid" jdbcType="CHAR" column="uuid" />
<result property="code" jdbcType="VARCHAR" column="code" />
<result property="expireTime" jdbcType="TIMESTAMP" column="expireTime" />
</resultMap>
<delete id="deleteBatch" parameterType="String">
delete from sys_captcha where 1>2
or uuid in
<foreach collection="array" item="uuid" index="no" open="(" separator="," close=")">
#{uuid}
</foreach>
</delete>
10;最后一步使用,把这行代码加入到登陆接口,把刚才前端的uuid和验证码让前端传过来,和数据库去做比较,如果错误,直接提示验证码错误
boolean validate = verCodeService.validate(uuid, captcha);
if (!validate) {
resultMap.put(“500”,“验证码不正确”);
}