zoukankan      html  css  js  c++  java
  • 生成动态验证码

    1)编写工具类

    package com.icucoder.util;
    
    import javax.imageio.ImageIO;
    import java.awt.*;
    import java.awt.image.BufferedImage;
    import java.io.IOException;
    import java.io.OutputStream;
    import java.util.Random;
    
    /**
     * @Author : icucoder
     * @Time : 2021/3/29 16:17
     */
    
    
    public class CaptchaCodeUtil {
        /**
         * 验证码图片的宽度
         */
        private int width = 160;
        /**
         * 验证码图片的宽度
         */
        private int height = 40;
        /**
         * 干扰线的数量
         */
        private int lineCount = 20;
        /**
         * 验证码
         */
        private String code = null;
    
        /**
         * 验证码图片上字符个数
         */
        private int codeCount = 4;
    
        /**
         * 验证码图片Buffer
         */
        private BufferedImage buffImg = null;
    
        Random random = new Random();
    
        public CaptchaCodeUtil() {
            createImageCode();
        }
    
        /**
         * 指定宽高
         *
         * @param width
         * @param height
         */
        public CaptchaCodeUtil(int width, int height) {
            this.width = width;
            this.height = height;
            createImageCode();
        }
    
        /**
         * 指定宽高和干扰线的数量
         *
         * @param width
         * @param height
         * @param lineCount
         */
        public CaptchaCodeUtil(int width, int height, int lineCount) {
            this.width = width;
            this.height = height;
            this.lineCount = lineCount;
            createImageCode();
        }
    
        /**
         * 指定宽高、验证码字符个数、干扰线数量
         *
         * @param width
         * @param height
         * @param codeCount
         * @param lineCount
         */
        public CaptchaCodeUtil(int width, int height, int codeCount, int lineCount) {
            this.width = width;
            this.height = height;
            this.codeCount = codeCount;
            this.lineCount = lineCount;
            createImageCode();
        }
    
        /**
         * 指定宽高、验证码字符个数、干扰线数量、
         *
         * @param width
         * @param height
         * @param codeCount
         * @param lineCount
         * @param code
         */
        public CaptchaCodeUtil(int width, int height, int codeCount, int lineCount, String code) {
            this.width = width;
            this.height = height;
            this.codeCount = codeCount;
            this.lineCount = lineCount;
            createImageCode(code);
        }
    
        /**
         * 生成验证码
         */
        private void createImageCode() {
            // 字体的宽度
            int fontWidth = width / codeCount;
            // 字体的高度
            int fontHeight = height - 5;
            // 偏移量
            int codeY = height - 8;
    
            // 图像buffer
            buffImg = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
            Graphics g = buffImg.getGraphics();
            // 设置背景色
            g.setColor(getRandColor(200, 250));
            g.fillRect(0, 0, width, height);
    
            // 设置字体
            Font font = new Font("Fixedsys", Font.BOLD, fontHeight);
            g.setFont(font);
    
            // 设置干扰线
            setLine(g);
    
            // 添加噪点
            // 噪声率
            float yawpRate = 0.01f;
            int area = (int) (yawpRate * width * height);
            for (int i = 0; i < area; i++) {
                int x = random.nextInt(width);
                int y = random.nextInt(height);
                buffImg.setRGB(x, y, random.nextInt(255));
            }
            // 得到随机字符
            String str1 = randomStr(codeCount);
            this.code = str1;
            for (int i = 0; i < codeCount; i++) {
                String strRand = str1.substring(i, i + 1);
                g.setColor(getRandColor(1, 255));
                // a为要画出来的东西,x和y表示要画的东西最左侧字符的基线位于此图形上下文坐标系的 (x, y) 位置处
                g.drawString(strRand, i * fontWidth + 3, codeY);
            }
    
        }
    
        /**
         * 生成指定字符图片
         */
        private void createImageCode(String code) {
            // 字体的宽度
            int fontWidth = width / codeCount;
            // 字体的高度
            int fontHeight = height - 5;
            int codeY = height - 8;
    
            // 图像buffer
            buffImg = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
            Graphics g = buffImg.getGraphics();
            // 设置背景色
            g.setColor(getRandColor(200, 250));
            g.fillRect(0, 0, width, height);
    
            // 设置字体
            Font font = new Font("Fixedsys", Font.BOLD, fontHeight);
            g.setFont(font);
    
            // 设置干扰线
            setLine(g);
    
            // 添加噪点
            // 噪声率
            float yawpRate = 0.01f;
            int area = (int) (yawpRate * width * height);
            for (int i = 0; i < area; i++) {
                int x = random.nextInt(width);
                int y = random.nextInt(height);
    
                buffImg.setRGB(x, y, random.nextInt(255));
            }
    
            this.code = code;
            for (int i = 0; i < code.length(); i++) {
                String strRand = code.substring(i, i + 1);
                g.setColor(getRandColor(1, 255));
                // a为要画出来的东西,x和y表示要画的东西最左侧字符的基线位于此图形上下文坐标系的 (x, y) 位置处
                g.drawString(strRand, i * fontWidth + 3, codeY);
            }
    
        }
    
        /**
         * 设置干扰线
         *
         * @param g
         */
        private void setLine(Graphics g) {
            for (int i = 0; i < lineCount; i++) {
                int xs = random.nextInt(width);
                int ys = random.nextInt(height);
                int xe = xs + random.nextInt(width);
                int ye = ys + random.nextInt(height);
                g.setColor(getRandColor(1, 255));
                g.drawLine(xs, ys, xe, ye);
            }
    
        }
    
        /**
         * 得到随机字符
         *
         * @param n
         * @return
         */
        public String randomStr(int n) {
            String str1 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890";
            String str2 = "";
            int len = str1.length() - 1;
            double r;
            for (int i = 0; i < n; i++) {
                r = (Math.random()) * len;
                str2 = str2 + str1.charAt((int) r);
            }
            return str2;
        }
    
        /**
         * 得到随机颜色
         *
         * @param fc
         * @param bc
         * @return
         */
        private Color getRandColor(int fc, int bc) {
            // 给定范围获得随机颜色
            if (fc > 255) {
                fc = 255;
            }
            if (bc > 255) {
                bc = 255;
            }
            int r = fc + random.nextInt(bc - fc);
            int g = fc + random.nextInt(bc - fc);
            int b = fc + random.nextInt(bc - fc);
            return new Color(r, g, b);
        }
    
        /**
         * 产生随机字体
         */
        private Font getFont(int size) {
            Random random = new Random();
            Font font[] = new Font[5];
            font[0] = new Font("Ravie", Font.PLAIN, size);
            font[1] = new Font("Antique Olive Compact", Font.PLAIN, size);
            font[2] = new Font("Fixedsys", Font.PLAIN, size);
            font[3] = new Font("Wide Latin", Font.PLAIN, size);
            font[4] = new Font("Gill Sans Ultra Bold", Font.PLAIN, size);
            return font[random.nextInt(5)];
        }
    
    
        /**
         * 扭曲方法
         *
         * @param g
         * @param w1
         * @param h1
         * @param color
         */
        private void shear(Graphics g, int w1, int h1, Color color) {
            shearX(g, w1, h1, color);
            shearY(g, w1, h1, color);
        }
    
        private void shearX(Graphics g, int w1, int h1, Color color) {
    
            int period = random.nextInt(2);
    
            boolean borderGap = true;
            int frames = 1;
            int phase = random.nextInt(2);
    
            for (int i = 0; i < h1; i++) {
                double d = (double) (period >> 1)
                        * Math.sin((double) i / (double) period
                        + (6.2831853071795862D * (double) phase)
                        / (double) frames);
                g.copyArea(0, i, w1, 1, (int) d, 0);
                if (borderGap) {
                    g.setColor(color);
                    g.drawLine((int) d, i, 0, i);
                    g.drawLine((int) d + w1, i, w1, i);
                }
            }
    
        }
    
        private void shearY(Graphics g, int w1, int h1, Color color) {
    
            int period = random.nextInt(40) + 10;
    
            boolean borderGap = true;
            int frames = 20;
            int phase = 7;
            for (int i = 0; i < w1; i++) {
                double d = (double) (period >> 1)
                        * Math.sin((double) i / (double) period
                        + (6.2831853071795862D * (double) phase)
                        / (double) frames);
                g.copyArea(i, 0, 1, h1, 0, (int) d);
                if (borderGap) {
                    g.setColor(color);
                    g.drawLine(i, (int) d, i, 0);
                    g.drawLine(i, (int) d + h1, i, h1);
                }
    
            }
    
        }
    
        public void write(OutputStream sos) throws IOException {
            ImageIO.write(buffImg, "png", sos);
            sos.close();
        }
    
        public BufferedImage getBuffImg() {
            return buffImg;
        }
    
        public String getCode() {
            return code.toLowerCase();
        }
    }
    

     2)编写接口

    package com.icucoder.controller;
    
    import com.icucoder.util.CaptchaCodeUtil;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.*;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    import java.util.UUID;
    
    /**
     * @Author : icucoder
     * @Time : 2021/3/28 14:22
     * https://blog.csdn.net/lzxlfly/article/details/93381526
     */
    @Controller
    @RequestMapping("/code")
    public class CodeController {
    
        @RequestMapping("/")
        @ResponseBody
        public String captchaId() {
            String captchaId = UUID.randomUUID().toString().replace("-", "");
            return captchaId;
        }
    
        @GetMapping("/{captchaId}")
        public void getCaptcha(@PathVariable("captchaId") String captchaId, HttpServletRequest request, HttpServletResponse response) throws IOException {
            String sCode = new CaptchaCodeUtil().randomStr(4);
            request.getSession().setAttribute(captchaId, sCode);
            CaptchaCodeUtil vCode = new CaptchaCodeUtil(116, 36, 4, 10, sCode);
            vCode.write(response.getOutputStream());
        }
    
        @GetMapping("/{captchaId}/{uCode}")
        @ResponseBody
        public String verifyCaptcha(@PathVariable("captchaId") String captchaId, @PathVariable("uCode") String uCode, HttpServletRequest request) {
            String sCode = (String) request.getSession().getAttribute(captchaId);
            System.out.println("sCode:"+sCode);
            if (!uCode.equals(sCode)) {
                return "cpathca error";
            }
            return "captcha success";
        }
    }
    

     3)使用

    (1)访问http://127.0.0.1:8080/code/,生成验证码

    (2)访问http://127.0.0.1:8080/code/66d09cef9b554ff09a7bf3b79e41f40b,生成验证码

    (3)访问http://127.0.0.1:8080/code/66d09cef9b554ff09a7bf3b79e41f40b/5gK7,校验验证码


    如果你真心觉得文章写得不错,而且对你有所帮助,那就不妨小小打赏一下吧,如果囊中羞涩,不妨帮忙“推荐"一下,您的“推荐”和”打赏“将是我最大的写作动力!

    本文版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接.
    qq群 微信
  • 相关阅读:
    读书笔记之理想设计的特征
    一些javascript 变量声明的 疑惑
    LINQ 使用方法
    Google MySQL tool releases
    读书笔记之设计的层次
    EF之数据库连接问题The specified named connection is either not found in the configuration, not intended to be used with the Ent
    转载 什么是闭包
    javascript面向对象起步
    Tips
    数据结构在游戏中的应用
  • 原文地址:https://www.cnblogs.com/hoaprox/p/14725330.html
Copyright © 2011-2022 走看看