springboot+thymeleaf+kaptcha实现验证码(配置)

springboot+thymeleaf+kaptcha实现验证码(配置)

一、引入依赖

	<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的技术整合所以会在这几天研究补充。。。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值