验证码的实现

这篇具有很好参考价值的文章主要介绍了验证码的实现。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

在跟着老师学习的过程中,对于验证码的实现有诸多启发,在此进行记录。

一、验证码的实现

这里其实已经封装好了一个工具类,只需要调用工具中的方法即可。我之前的疑惑是,怎么进行输出?其实是使用了一个字节输出流,也就是哪里访问这个servlet,哪里就可以进行输出。

在老师的例子中有个图片,这个图片的地址,就用来输出,

验证码的实现

那么这是哪里输出过来的呢?每次访问一次专门输出的servlet就可以。

验证码的实现

下面是该工具类的全部代码。一般来说直接调用outputVerifyImage(int w, int h, OutputStream os, int verifySize),这个方法,传入相关参数就可以了。它会返回文字版本的验证码,用于你进行判定。

package com.fldwws.utils;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Arrays;
import java.util.Random;

/**
 * 生成验证码工具类
 */
public class CheckCodeUtil {

    public static final String VERIFY_CODES = "123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    private static Random random = new Random();



    /**
     * 输出随机验证码图片流,并返回验证码值(一般传入输出流,响应response页面端,Web项目用的较多)
     *
     * @param w
     * @param h
     * @param os
     * @param verifySize
     * @return
     * @throws IOException
     */
    public static String outputVerifyImage(int w, int h, OutputStream os, int verifySize) throws IOException {
        String verifyCode = generateVerifyCode(verifySize);
        outputImage(w, h, os, verifyCode);
        return verifyCode;
    }

    /**
     * 使用系统默认字符源生成验证码
     *
     * @param verifySize 验证码长度
     * @return
     */
    public static String generateVerifyCode(int verifySize) {
        return generateVerifyCode(verifySize, VERIFY_CODES);
    }

    /**
     * 使用指定源生成验证码
     *
     * @param verifySize 验证码长度
     * @param sources    验证码字符源
     * @return
     */
    public static String generateVerifyCode(int verifySize, String sources) {
        // 未设定展示源的字码,赋默认值大写字母+数字
        if (sources == null || sources.length() == 0) {
            sources = VERIFY_CODES;
        }
        int codesLen = sources.length();
        Random rand = new Random(System.currentTimeMillis());
        StringBuilder verifyCode = new StringBuilder(verifySize);
        for (int i = 0; i < verifySize; i++) {
            verifyCode.append(sources.charAt(rand.nextInt(codesLen - 1)));
        }
        return verifyCode.toString();
    }

    /**
     * 生成随机验证码文件,并返回验证码值 (生成图片形式,用的较少)
     *
     * @param w
     * @param h
     * @param outputFile
     * @param verifySize
     * @return
     * @throws IOException
     */
    public static String outputVerifyImage(int w, int h, File outputFile, int verifySize) throws IOException {
        String verifyCode = generateVerifyCode(verifySize);
        outputImage(w, h, outputFile, verifyCode);
        return verifyCode;
    }



    /**
     * 生成指定验证码图像文件
     *
     * @param w
     * @param h
     * @param outputFile
     * @param code
     * @throws IOException
     */
    public static void outputImage(int w, int h, File outputFile, String code) throws IOException {
        if (outputFile == null) {
            return;
        }
        File dir = outputFile.getParentFile();
        //文件不存在
        if (!dir.exists()) {
            //创建
            dir.mkdirs();
        }
        try {
            outputFile.createNewFile();
            FileOutputStream fos = new FileOutputStream(outputFile);
            outputImage(w, h, fos, code);
            fos.close();
        } catch (IOException e) {
            throw e;
        }
    }

    /**
     * 输出指定验证码图片流
     *
     * @param w
     * @param h
     * @param os
     * @param code
     * @throws IOException
     */
    public static void outputImage(int w, int h, OutputStream os, String code) throws IOException {
        int verifySize = code.length();
        BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
        Random rand = new Random();
        Graphics2D g2 = image.createGraphics();
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

        // 创建颜色集合,使用java.awt包下的类
        Color[] colors = new Color[5];
        Color[] colorSpaces = new Color[]{Color.WHITE, Color.CYAN,
                Color.GRAY, Color.LIGHT_GRAY, Color.MAGENTA, Color.ORANGE,
                Color.PINK, Color.YELLOW};
        float[] fractions = new float[colors.length];
        for (int i = 0; i < colors.length; i++) {
            colors[i] = colorSpaces[rand.nextInt(colorSpaces.length)];
            fractions[i] = rand.nextFloat();
        }
        Arrays.sort(fractions);
        // 设置边框色
        g2.setColor(Color.GRAY);
        g2.fillRect(0, 0, w, h);

        Color c = getRandColor(200, 250);
        // 设置背景色
        g2.setColor(c);
        g2.fillRect(0, 2, w, h - 4);

        // 绘制干扰线
        Random random = new Random();
        // 设置线条的颜色
        g2.setColor(getRandColor(160, 200));
        for (int i = 0; i < 20; i++) {
            int x = random.nextInt(w - 1);
            int y = random.nextInt(h - 1);
            int xl = random.nextInt(6) + 1;
            int yl = random.nextInt(12) + 1;
            g2.drawLine(x, y, x + xl + 40, y + yl + 20);
        }

        // 添加噪点
        // 噪声率
        float yawpRate = 0.05f;
        int area = (int) (yawpRate * w * h);
        for (int i = 0; i < area; i++) {
            int x = random.nextInt(w);
            int y = random.nextInt(h);
            // 获取随机颜色
            int rgb = getRandomIntColor();
            image.setRGB(x, y, rgb);
        }
        // 添加图片扭曲
        shear(g2, w, h, c);

        g2.setColor(getRandColor(100, 160));
        int fontSize = h - 4;
        Font font = new Font("Algerian", Font.ITALIC, fontSize);
        g2.setFont(font);
        char[] chars = code.toCharArray();
        for (int i = 0; i < verifySize; i++) {
            AffineTransform affine = new AffineTransform();
            affine.setToRotation(Math.PI / 4 * rand.nextDouble() * (rand.nextBoolean() ? 1 : -1), (w / verifySize) * i + fontSize / 2, h / 2);
            g2.setTransform(affine);
            g2.drawChars(chars, i, 1, ((w - 10) / verifySize) * i + 5, h / 2 + fontSize / 2 - 10);
        }

        g2.dispose();
        ImageIO.write(image, "jpg", os);
    }

    /**
     * 随机颜色
     *
     * @param fc
     * @param bc
     * @return
     */
    private static 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 static int getRandomIntColor() {
        int[] rgb = getRandomRgb();
        int color = 0;
        for (int c : rgb) {
            color = color << 8;
            color = color | c;
        }
        return color;
    }

    private static int[] getRandomRgb() {
        int[] rgb = new int[3];
        for (int i = 0; i < 3; i++) {
            rgb[i] = random.nextInt(255);
        }
        return rgb;
    }

    private static void shear(Graphics g, int w1, int h1, Color color) {
        shearX(g, w1, h1, color);
        shearY(g, w1, h1, color);
    }

    private static 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 static void shearY(Graphics g, int w1, int h1, Color color) {

        int period = random.nextInt(40) + 10; // 50;

        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);
            }

        }

    }
}

二、点击验证码更换图片

这里的话其实就是一个js。但是有两个地方我一直出错

  1. 更换src。 老师使用的是原生的js,我使用的是jQuery,因为属性不一样一直不能实现点击后更换图片。

在jQuery中,这样可以更换src属性: $("#img_pre").attr("src", src_value);。在原生的js中,是选择好控件后直接.src = "src_value"

  1. 如何做到点击之后一直进行更换图片?

核心方法就是,访问servlet的路径每一次都不一样。每一次都不一样就可以不让浏览器进行缓存。那又如何做到每次都不一样呢?在访问的src后面加上时间的毫秒值.要注意的是,加上后面其他的值,需要加上一个英文状态下的问号,这个地方非常容易忽视。

验证码的实现

三、用户登录的时候如何判定验证码是否正确?

到这一步其实就并不困难了。因为每一次生成验证码图片的时候都会返回一个文字版本的验证码。只要我们保存这个文字,再拿到用户输入的文字进行匹配,如果匹配不上那就提示错误。❌。那这里也有两个地方需要注意一下。

  1. 文字的验证码的存储。这个需要存储到session域中,这个无需多讲。

验证码的实现

  1. 比对验证码的方法。

这里采取的是,如果比对不上,那提示错误❌,并且再次返回到注册界面,然后再return。

验证码的实现

总结一下啊

  1. 用什么来输出验证码图片?

输出流,写到servlet里面,哪里需要就直接调用这个servlet

  1. 怎么确保点击一次更换一张验证码?

每次点击事件后更换src的地址值,要确保每次地址值都不一样还需要加上时间的毫秒值。在servlet中拼接其他字符需要加上英文状态下的?

  1. 如何进行判断用户输入的验证码是否正确?

保存返回值就可以了,保存到session中,再比对用户输入的就可以。

  1. 用户验证码的逻辑是怎么样的?

填写错误之后先提示,然后仍然跳转到注册界面,最后直接return掉这一次的servlet请求。后面正确的逻辑就不会执行。文章来源地址https://www.toymoban.com/news/detail-467371.html

到了这里,关于验证码的实现的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 和大家分享一下学习清风老师的数学建模课的过程

    作为一名大一数学系的新生,就读于某中上游985大学,为了锻炼自己的能力和为以后保研做准备,所以想参加数学建模大赛,于是便早早的组好了队友,想着早起的鸟儿有虫吃,起初是在学长学姐的建议下买了司守奎老师的《数学建模算法与应用》想着看书自学大干一番,可

    2024年04月25日
    浏览(23)
  • ChatGPT-在对于一段代码的分析过程中展示出的学习和分析能力!

    本人与ChatGPT完整的交流过程如下: ==我:给你一段代码,帮我分析一下执行情况 ==ChatGPT:请提供代码并说明任何特殊要求。 ==我:代码如下: ==ChatGPT:这段代码创建了一个线程池,该线程池有3个线程,然后循环3次创建父任务,每个父任务在线程池上执行。父任务执行时会

    2023年04月16日
    浏览(21)
  • 用于读取验证码的 OCR 模型

    此示例演示了使用功能 API 构建的简单 OCR 模型。除了结合 CNN 和 RNN 之外,它还说明了如何实例化新层并将其用作“端点层”来实现 CTC 损失。 我们来下载数据。

    2024年02月06日
    浏览(28)
  • 织梦DedeCms取消后台登陆验证码的方法示例

    首先模拟会员登录和退出,有两个重要文件,一个是include下的memberlogin.class.php和include/helpers下的cache.helper.php文件。 原理为:memberlogin.class.php通过使用缓存助手 helper(\\\'cache\\\'),然后/member/config.php 文件引入memberlogin.class.php文件实现模拟登录和退出。 模拟会员登录代码 引入/memb

    2024年02月02日
    浏览(32)
  • Selenium破解滑动验证码的原理及解决思路

    🍅 视频学习: 文末有免费的配套视频可观看 🍅  点击文末小卡片 ,免费获取软件测试全套资料,资料在手,涨薪更快  1、获取页面元素信息: 使用Selenium打开目标网页,并通过相关方法获取滑块、背景图等元素的位置和属性信息。可以使用Selenium提供的定位方法(如xpa

    2024年02月20日
    浏览(36)
  • Jmeter接口测试 —— jmeter对图片验证码的处理

    在web端的登录接口经常会有图片验证码的输入,而且每次登录时图片验证码都是随机的;当通过jmeter做接口登录的时候要对图片验证码进行识别出图片中的字段,然后再登录接口中使用; 1、通过ocrserver工具识别图片验证码; 如下图:解压后双击OcrServer.exe;然后电脑的右下角

    2024年02月05日
    浏览(40)
  • 使用Selenium破解滑动验证码的原理及解决思路

    1、获取页面元素信息: 使用Selenium打开目标网页,并通过相关方法获取滑块、背景图等元素的位置和属性信息。可以使用Selenium提供的定位方法(如xpath、CSS选择器等)来找到这些元素。 可以使用find_element_by_xpath或find_element_by_css_selector等方法来获取滑块和背景图元素的位置和

    2024年02月09日
    浏览(38)
  • Python爬虫之极验滑动验证码的识别

    上节我们了解了可以直接利用 tesserocr 来识别简单的图形验证码。近几年出现了一些新型验证码,其中比较有代表性的就是极验验证码,它需要拖动拼合滑块才可以完成验证,相对图形验证码来说识别难度上升了几个等级。本节将讲解极验验证码的识别过程。 1. 本节目标 我们

    2024年02月22日
    浏览(38)
  • 使用隧道HTTP时如何解决网站验证码的问题?

    使用代理时,有时候会遇到网站验证码的问题。验证码是为了防止机器人访问或恶意行为而设置的一种验证机制。当使用代理时,由于请求的源IP地址被更改,可能会触发网站的验证码机制。以下是解决网站验证码问题的几种方法: 1. 使用高匿代理服务器:选择高匿代理服务

    2024年02月14日
    浏览(27)
  • Python scrapy爬取带验证码的列表数据

    首先所需要的环境:(我用的是Python2的,可以选择python3,具体遇到的问题自行解决,目前我这边几百万的数据量爬取) 环境: 直接贴代码具体需要注意的特殊颜色标出有注释 pipelines存数据库这个就不说了根据自己的业务 注:目前我网站验证码比较简单可以直接使用pytess

    2024年01月18日
    浏览(28)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包