天天看點

springboot(二十六)springboot+kaptcha生成驗證碼并校驗

作者:聰明的晚風zqw
使用springboot+kaptcha生成驗證碼并校驗

1 添加kaptcha依賴

gradle:

implementation group: 'com.github.penggle', name: 'kaptcha', version: '2.3.2'           

maven:

<dependency>
    <groupId>com.github.penggle</groupId>
    <artifactId>kaptcha</artifactId>
    <version>2.3.2</version>
</dependency>           

2 配置檔案内配置功能開啟開關

#############################kaptcha驗證碼相關配置##################################################################
kaptcha.enabled=true           

3 配置kaptcha

這裡使用@ConditionalOnProperty讀取配置檔案内配置,判斷是否進行配置

package com.iscas.base.biz.config.verification.code;

import com.google.code.kaptcha.impl.DefaultKaptcha;
import com.google.code.kaptcha.util.Config;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.Properties;

/**
 * //TODO
 *
 * @author zhuquanwen
 * @vesion 1.0
 * @date 2020/8/17 20:52
 * @since jdk1.8
 */
@Configuration
@ConditionalOnProperty(havingValue = "true", value = "kaptcha.enabled", matchIfMissing = false)
public class VerificationCodeConfig {
    @Bean
    public DefaultKaptcha getKaptcheCode() {
        DefaultKaptcha defaultKaptcha = new DefaultKaptcha();
        Properties properties = new Properties();
        properties.setProperty("kaptcha.border", "no");
        properties.setProperty("kaptcha.textproducer.font.color", "black");
        properties.setProperty("kaptcha.image.width", "100");
        properties.setProperty("kaptcha.image.height", "36");
        properties.setProperty("kaptcha.textproducer.font.size", "30");
        properties.setProperty("kaptcha.obscurificator.impl", "com.google.code.kaptcha.impl.ShadowGimpy");
        properties.setProperty("kaptcha.session.key", "code");
        properties.setProperty("kaptcha.noise.impl", "com.google.code.kaptcha.impl.NoNoise");
        properties.setProperty("kaptcha.background.clear.from", "232,240,254");
        properties.setProperty("kaptcha.background.clear.to", "232,240,254");
        properties.setProperty("kaptcha.textproducer.char.length", "4");
        properties.setProperty("kaptcha.textproducer.font.names", "彩雲,宋體,楷體,微軟雅黑");
        Config config = new Config(properties);
        defaultKaptcha.setConfig(config);
        return defaultKaptcha;
    }
}           

4 編寫controller内的接口

第一個接口擷取驗證碼,第二個接口進行驗證碼校驗

package com.iscas.base.biz.controller.common;

import com.google.code.kaptcha.Constants;
import com.google.code.kaptcha.Producer;
import com.iscas.base.biz.util.SpringUtils;
import com.iscas.templet.common.BaseController;
import com.iscas.templet.common.ResponseEntity;
import io.swagger.annotations.Api;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.imageio.ImageIO;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.image.BufferedImage;
import java.util.Objects;

/**
 *
 * @author zhuquanwen
 * @vesion 1.0
 * @date 2020/8/17 20:49
 * @since jdk1.8
 */
@RestController
@Api(description = "驗證碼控制器")
@Slf4j
@ConditionalOnProperty(havingValue = "true", value = "kaptcha.enabled", matchIfMissing = false)
public class VerificationCodeController extends BaseController {
    @Autowired
    private Producer producer;

    /**
     * 擷取驗證碼
     * */
    @GetMapping("/verification/code")
    public void getKaptchaImage(HttpServletRequest request, HttpServletResponse response) throws Exception {
        response.setDateHeader("Expires", 0);
        response.setHeader("Cache-Control", "no-store, no-cache, must-revalidate");
        response.addHeader("Cache-Control", "post-check=0, pre-check=0");
        response.setHeader("Pragma", "no-cache");
        response.setContentType("image/jpeg");
        String capText = producer.createText();
        log.debug("*************驗證碼已經生成為:{}******************", capText);
        // 将驗證碼存于session中,分布式部署需要共享session,或存入共享存儲中
        request.getSession().setAttribute(Constants.KAPTCHA_SESSION_KEY, capText);
        BufferedImage bi = producer.createImage(capText);
        ServletOutputStream out = response.getOutputStream();
        // 向頁面輸出驗證碼
        ImageIO.write(bi, "jpg", out);
        try {
            // 清空緩存區
            out.flush();
        } finally {
            // 關閉輸出流
            out.close();
        }
    }

    /**
     * 校驗驗證碼
     * */
    @GetMapping("/verification/code/verify")
    public ResponseEntity verify(String code) throws Exception {
        ResponseEntity response = getResponse();
        // 擷取Session中驗證碼
        Object storeCode = SpringUtils.getSession().getAttribute(Constants.KAPTCHA_SESSION_KEY);
        // 判斷驗證碼是否為空
        if (StringUtils.isEmpty(code)) {
            response.setValue(false);
        } else {
            // 校驗驗證碼的正确與否
            boolean result = Objects.equals(code, storeCode);
            if (result) {
                //将驗證碼從session中删掉
                SpringUtils.getSession().removeAttribute(Constants.KAPTCHA_SESSION_KEY);
            }
            response.setValue(result);
        }
        return response;
    }
}           

5 前端測試代碼

送出使用者名密碼前先進行驗證碼校驗

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8" />
    <script type="text/javascript" src="CryptoJS/rollups/aes.js"></script>
    <script type="text/javascript" src="CryptoJS/components/mode-ecb.js"></script>
    <script type="text/javascript" src="CryptoJS/components/enc-base64.js"></script>
    <script type="text/javascript" src="CryptoJS/components/core.js"></script>
    <script>
        var $1 = function(id) {
            return document.getElementById(id);
        };
        ......
        function tosubmit(){
            //驗證驗證碼
            var xhr = new XMLHttpRequest();
            xhr.withCredentials = true;
            xhr.open('get', 'http://localhost:7901/demo/verification/code/verify?code=' + $1("code").value);
            xhr.setRequestHeader("Content-type", "application/json;charset=utf-8");
            //發送請求
            xhr.send();
            xhr.onreadystatechange = function () {
                if (xhr.readyState == 4 && xhr.status == 200) {
                    var jsonx = JSON.parse(xhr.responseText);
                    if(jsonx.status != 200){
                        console.log(jsonx.message);
                        var verifySuccess = jsonx.value;
                        if (verifySuccess == true) {
                            //發送使用者名密碼
                            submitUserAndPwd();
                        } else {
                            alert("驗證碼校驗失敗");
                        }
                    }else{
                        console.log(jsonx.data);
                    }
                }else{
                    // var json = JSON.parse(xhr.responseText);
                    console.log(xhr.responseText);
                }
            };

        }

        function submitUserAndPwd() {
            ......
        }
    </script>
    <title>登入</title>
</head>
<body>
使用者名:<input type="text" value="" id="user"/> <br/>
密碼:<input type="text" id="pwd" /><br/>
驗證碼:<img src="http://localhost:7901/demo/verification/code" onclick="this.src=this.src+'?m='+Math.random();"/>
        <input type="text", id = "code"/><br/>
<input type="button" value="送出" onclick="tosubmit();"/>
</body>
</html>           

巨醜無比的登入頁來了,也能實作驗證碼校驗了

springboot(二十六)springboot+kaptcha生成驗證碼并校驗

繼續閱讀