Spring Boot 集成验证码

Spring Boot 集成验证码

方法 1

在 pom.xml 文件中引入依赖:

<!-- https://mvnrepository.com/artifact/com.github.axet/kaptcha -->
<dependency>
    <groupId>com.github.axet</groupId>
    <artifactId>kaptcha</artifactId>
    <version>0.0.9</version>
</dependency>

在 config 包中新建验证码配置类:

import java.util.Properties;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import com.google.code.kaptcha.Constants;
import com.google.code.kaptcha.Producer;
import com.google.code.kaptcha.impl.DefaultKaptcha;
import com.google.code.kaptcha.util.Config;

/**
 * <p> 验证码配置
 * @author mk
 * @date 2020.01.04
 *
 */
@Configuration
public class KaptchaConfig {

    @Bean
    public Producer producer() {
        Properties properties = new Properties();
        properties.put(Constants.KAPTCHA_BORDER, "no");
        properties.put(Constants.KAPTCHA_TEXTPRODUCER_FONT_COLOR, "black");
        properties.put(Constants.KAPTCHA_TEXTPRODUCER_CHAR_SPACE, "5");
        
        DefaultKaptcha defaultKaptcha = new DefaultKaptcha();
        defaultKaptcha.setConfig(new Config(properties));
        
        return defaultKaptcha;
    }
}

在 controller 包中新建控制器类:

import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Date;

import javax.imageio.ImageIO;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.tomcat.util.http.fileupload.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import com.google.code.kaptcha.Constants;
import com.google.code.kaptcha.Producer;

/**
 * <p> 登录控制器
 * @author mk
 * @date 2020.01.04
 *
 */
@RestController
public class LoginController {

    @Autowired
    private Producer producer;
    
    /**
     * <p> 验证码
     * <p> 参考:com.google.code.kaptcha.servlet.KaptchaServlet
     * @param request
     * @param response
     * @throws IOException
     */
    @GetMapping("captcha.jpg")
    public void captcha(HttpServletRequest request, HttpServletResponse response) {
        // 参考:https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Caching_FAQ
        response.setHeader("Cache-Control", "no-store, no-cache"); // Set standard HTTP/1.1 no-cache headers
        response.setContentType("image/jpeg"); // return a jpeg
        
        String text = producer.createText(); // create the text for the image
        BufferedImage image = producer.createImage(text); // create the image with the text
        
        HttpSession session = request.getSession();
        // store the text in the session
        session.setAttribute(Constants.KAPTCHA_SESSION_CONFIG_KEY, text);
        // store the date in the session so that it can be compared
        // against to make sure someone hasn't taken too long to enter
        // their captcha
        session.setAttribute(Constants.KAPTCHA_SESSION_CONFIG_DATE, new Date());
        
        ServletOutputStream out = null;
        try {
            out = response.getOutputStream();
            ImageIO.write(image, "jpg", out); // write the data out
        } catch (IOException e) {
            session.removeAttribute(Constants.KAPTCHA_SESSION_CONFIG_KEY);
            session.removeAttribute(Constants.KAPTCHA_SESSION_CONFIG_DATE);
            e.printStackTrace();
        } finally {
            IOUtils.closeQuietly(out); // 关闭输出流
        }
    }
}

运行启动类,访问 http://localhost:8080/captcha.jpg
在这里插入图片描述

方法 2

使用 Hutool 工具包提供的图形验证码

引入 Hutool 工具包的依赖:

<hutool-all.version>5.0.7</hutool-all.version>
<dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-all</artifactId>
    <version>${hutool-all.version}</version>
</dependency>

图形验证码控制器类:

import java.io.IOException;

import javax.imageio.ImageIO;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.tomcat.util.http.fileupload.IOUtils;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import cn.hutool.captcha.CaptchaUtil;
import cn.hutool.captcha.LineCaptcha;

@RestController
public class CaptchaController {

    @GetMapping("/captcha")
    public void captcha(HttpServletRequest request, HttpServletResponse response, HttpSession session) {
        String referer = request.getHeader("referer");
        if ((referer != null) && (referer.equalsIgnoreCase("http://localhost:8080/login.html"))) { // 来自登录页面的请求
            int width = 116;
            int height = 36;
            int codeCount = 4;
            int lineCount = 10;

            // 创建图形验证码
            LineCaptcha lineCaptcha = CaptchaUtil.createLineCaptcha(width, height, codeCount, lineCount);

            ServletOutputStream out = null;
            try {
                // 将图形验证码写到响应输出流
                out = response.getOutputStream();
//                lineCaptcha.write(out);
                ImageIO.write(lineCaptcha.getImage(), "JPEG", out);
                out.flush();

                // 保存验证码
                String code = lineCaptcha.getCode();
                session.setAttribute("code", code);
                System.out.println(code);
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                IOUtils.closeQuietly(out);
            }
        } else { // 拒绝其他路径的请求
            response.setStatus(HttpStatus.NOT_FOUND.value());
        }
    }
}

在图形验证码控制器类中,通过查询 Referer 请求头判断请求验证码的来源地址。

Referer 请求头包含了当前请求页面的来源页面的地址,即表示当前页面是通过此来源页面里的链接进入的。

参考:Referer

登录页面 src/main/resources/static/login.html:

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>登录</title>
</head>
<body>
    <form class="login-page" action="/login" method="post">
        <div class="form">
            <h3>账户登录</h3>
            <input type="text" placeholder="用户名" name="username" required="required" />
            <input type="password" placeholder="密码" name="password" required="required" />
            <span style="display: inline">
                <input type="text" name="captcha" placeholder="验证码" />
                <img src="/captcha" style="width: 100px; height: 22px"/>
            </span>
            <button type="submit">登录</button>
        </div>
    </form>
</body>
</html>

图形验证码的效果:
在这里插入图片描述

通过 Referer 请求头限制非登录页面访问图形验证码的效果:
在这里插入图片描述

发布了36 篇原创文章 · 获赞 0 · 访问量 1862

猜你喜欢

转载自blog.csdn.net/qq_29761395/article/details/103850352