springboot 集成kaptcha实现验证码的生成校验

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/HXNLYW/article/details/100013220

一、添加kaptcha依赖:

<kaptcha.version>2.3.2</kaptcha.version>

<!-- https://mvnrepository.com/artifact/com.github.penggle/kaptcha -->
<dependency>
	<groupId>com.github.penggle</groupId>
	<artifactId>kaptcha</artifactId>
	<version>${kaptcha.version}</version>
</dependency>

二、kaptcha配置类:

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;

/**
 * @author gourd
 */
@Configuration
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", "yes");
		// 边框颜色
		properties.setProperty("kaptcha.border.color", "105,179,90");
		// 图片宽
		properties.setProperty("kaptcha.image.width", "110");
		// 图片高
		properties.setProperty("kaptcha.image.height", "40");
		// 字体颜色
		properties.setProperty("kaptcha.textproducer.font.color", "red");
		// 字体大小
		properties.setProperty("kaptcha.textproducer.font.size", "30");
		// session key
		properties.setProperty("kaptcha.session.key", "code");
		// 文字间隔
		properties.setProperty("kaptcha.textproducer.char.space", "3");
		// 验证码长度
		properties.setProperty("kaptcha.textproducer.char.length", "4");
		// 字体
		properties.setProperty("kaptcha.textproducer.font.names", "Arial,Courier");
		// 验证码的取值范围
		properties.setProperty("kaptcha.textproducer.char.string", "abcdefhkmnprstuwxz0123456789ABCEFGHIJKLMNPRSTUWXZ");
		// 图片的样式
		properties.setProperty("kaptcha.obscurificator.impl", "com.google.code.kaptcha.impl.WaterRipple");
		// 干扰颜色,合法值: r,g,b 或者 white,black,blue
		properties.setProperty("kaptcha.noise.color", "black");
		// 干扰实现类
		properties.setProperty("kaptcha.noise.impl", "com.google.code.kaptcha.impl.DefaultNoise");
		// 背景颜色渐变,开始颜色
		properties.setProperty("kaptcha.background.clear.from", "lightGray");
		// 背景颜色渐变,结束颜色
		properties.setProperty("kaptcha.background.clear.to", "white");

		Config config = new Config(properties);
		defaultKaptcha.setConfig(config);
		return defaultKaptcha;
	}
}

三、生成、校验验证码逻辑:

import com.gourd.common.data.BaseResponse;

/**
 * @author gourd
 * @date 2018-12-26
 */
public interface ValidateCodeService {


    /**
     * 生成图形验证码
     *
     * @return
     */
    BaseResponse generateImageCode();
    /**
     * 验证验证码
     *
     * @return
     */
    BaseResponse validateImageCode(String tryCode);

}
@Service
@Slf4j
public class ValidateCodeServiceImpl implements ValidateCodeService {

    /**
     * 生成图形验证码
     * @return
     */
    @Override
    public BaseResponse generateImageCode(){
        HttpServletRequest request = RequestHolder.getRequest();
        HttpServletResponse response = RequestHolder.getResponse();
        byte[] captchaChallengeAsJpeg;
        try(ByteArrayOutputStream jpegOutputStream = new ByteArrayOutputStream()){
            // 生成验证码字符串并保存到session中
            String createText = defaultKaptcha.createText();
            HttpSession session = request.getSession();
            session.setAttribute("rightCode", createText);

            // 使用生成的验证码字符串返回一个BufferedImage对象并转为byte写入到byte数组中
            BufferedImage challenge = defaultKaptcha.createImage(createText);
            ImageIO.write(challenge,"jpg",jpegOutputStream);

            // 定义response输出类型为image/jpeg类型,使用response输出流输出图片的byte数组
            captchaChallengeAsJpeg = jpegOutputStream.toByteArray();
            response.setHeader("Cache-Control", "no-store");
            response.setHeader("Pragma", "no-cache");
            response.setDateHeader("Expires",0);
            response.setContentType("image/jpeg");

            // 清空response,解决错误:java.lang.IllegalStateException: getOutputStream() has already been called for this response
            response.reset();
            ServletOutputStream servletOutputStream = response.getOutputStream();
            servletOutputStream.write(captchaChallengeAsJpeg);
            servletOutputStream.flush();
            servletOutputStream.close();
        }catch (IOException e) {
            log.error("生成图形验证码失败:{}",e);
            throw new ServiceException("生成图形验证码失败");
        }
        return BaseResponse.ok("生成验证码成功");
    }


    /**
     * 验证图形验证码
     *
     * @return
     */
    @Override
    public BaseResponse validateImageCode(String tryCode) {
        HttpServletRequest request = RequestHolder.getRequest();
        String rightCode = (String) request.getSession().getAttribute("rightCode");
        if (!rightCode.equalsIgnoreCase(tryCode)) {
            return BaseResponse.failure("验证码不正确");
        }
        return BaseResponse.ok("验证码正确");
    }

}

避雷

需要在response.getOutputStream()之前加上response.reset();

否则会报错:java.lang.IllegalStateException: getOutputStream() has already been called for this response

四、调用测试:

import com.gourd.common.data.BaseResponse;
import com.gourd.common.validation.service.ValidateCodeService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

/**
 * @author gourd
 * createAt: 2018/9/17
 */

@RestController
@Api(tags = "validateCode",description = "验证码控制器")
@RequestMapping("/code")
@Slf4j
public class ValidateCodeController {

    @Autowired
    private ValidateCodeService validateCodeService;

    /**
     * 生成图形验证码
     *
     * @return
     */
    @GetMapping(value = "/image")
    @ApiOperation(value = "生成图形验证码")
    public BaseResponse generateImageCode(){
        return validateCodeService.generateImageCode();
    }
    /**
     * 验证图形验证码
     *
     * @return
     */
    @GetMapping(value = "/verification")
    @ApiOperation(value = "验证图形验证码")
    public BaseResponse validateImageCode(@RequestParam String tryCode){
        return validateCodeService.validateImageCode(tryCode);
    }

}

html页面:

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.w3.org/1999/xhtml" layout:decorator="layout">
<head lang="en">
    <meta charset="UTF-8"></meta>
    <title>验证码</title>
    <script src="http://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script>
</head>
<body>
<div>
    <!-- 后面添加参数起到清除缓存作用 -->
    <img alt="验证码" onclick="this.src='/code/image?d='+new Date()*1" src="/code/image" />
</div>
<form id="form">
    <input type="text" name="tryCode" />
    <input value="提交" type="button" onclick="validate()"/>
</form>
</body>
<script>
    // 匿名函数的写法
    var validate = function(){
        $.ajax({
            //几个参数需要注意一下
            type: "GET",//方法类型
            dataType: "json",//预期服务器返回的数据类型
            url: "/code/verification" ,//url
            data: $('#form').serialize(),
            success: function (result) {
                alert(result.msg);
            },
            error : function() {
                alert("异常!");
            }
        });
    }

</script>
</html>

效果:

附:

Constant 描述 默认值
kaptcha.border 图片边框,合法值:yes , no yes
kaptcha.border.color 边框颜色,合法值: r,g,b (and optional alpha) 或者 white,black,blue. black
kaptcha.border.thickness 边框厚度,合法值:>0 1
kaptcha.image.width 图片宽 200
kaptcha.image.height 图片高 50
kaptcha.producer.impl 图片实现类 com.google.code.kaptcha.impl.DefaultKaptcha
kaptcha.textproducer.impl 文本实现类 com.google.code.kaptcha.text.impl.DefaultTextCreator
kaptcha.textproducer.char.string 文本集合,验证码值从此集合中获取 abcde2345678gfynmnpwx
kaptcha.textproducer.char.length 验证码长度 5
kaptcha.textproducer.font.names 字体 Arial
kaptcha.textproducer.font.size 字体大小 40px.
kaptcha.textproducer.font.color 字体颜色,合法值: r,g,b 或者 white,black,blue. black
kaptcha.textproducer.char.space 文字间隔 2
kaptcha.noise.impl 干扰实现类 com.google.code.kaptcha.impl.DefaultNoise
kaptcha.noise.color 干扰 颜色,合法值: r,g,b 或者 white,black,blue. black
kaptcha.obscurificator.impl

图片样式:

水纹com.google.code.kaptcha.impl.WaterRipple 鱼眼com.google.code.kaptcha.impl.FishEyeGimpy 阴影com.google.code.kaptcha.impl.ShadowGimpy

com.google.code.kaptcha.impl.WaterRipple
kaptcha.background.impl 背景实现类 com.google.code.kaptcha.impl.DefaultBackground
kaptcha.background.clear.from 背景颜色渐变,开始颜色 lightGray
kaptcha.background.clear.to 背景颜色渐变,结束颜色 white
kaptcha.word.impl 文字渲染器 com.google.code.kaptcha.text.impl.DefaultWordRenderer
kaptcha.session.key session key KAPTCHA_SESSION_KEY
kaptcha.session.date session date KAPTCHA_SESSION_DATE

猜你喜欢

转载自blog.csdn.net/HXNLYW/article/details/100013220