验证码功能实现

使用google的kaptcha包实现,可预定义验证码内容。

pom.xml:

<dependency>
            <groupId>com.google.code.kaptcha</groupId>
            <artifactId>kaptcha</artifactId>
            <version>2.3</version>
            <!--Kaptcha针对1.5和1.4提供了不同的分发包,这里使用classifier来区分-->
            <classifier>jdk15</classifier>
        </dependency>

CaptchaService:

package net.deniro.captcha;

import java.util.List;

/**
 * 验证码
 *
 * @author deniro
 *         15-2-24上午10:49
 */
public interface CaptchaService {
    /**
     * 生成随机验证码主键
     *
     * @return
     * @throws CaptchaException
     */
    String generateCaptchaKey() throws CaptchaException;

    /**
     * 生成验证码图片
     *
     * @param captchaKey
     * @return
     * @throws CaptchaException
     */
    byte[] generateCaptchaImage(String captchaKey) throws CaptchaException;

    /**
     * 验证用户返回的主键和值
     *
     * @param captchaKey
     * @param captchaValue
     * @return
     * @throws CaptchaException
     */
    boolean validateCaptcha(String captchaKey, String captchaValue) throws CaptchaException;

    /**
     * 获取 预定义验证码图片的内容
     *
     * @return
     */
    List<String> getPreDefinedTexts();

    /**
     * 设置 预定义验证码图片的内容
     *
     * 提高可测试性
     *
     * @param preDefinedTexts
     */
    void setPreDefinedTexts(List<String> preDefinedTexts);
}

CaptchaServiceImpl:

package net.deniro.captcha;

import com.google.code.kaptcha.impl.DefaultKaptcha;
import com.google.code.kaptcha.util.Config;
import org.springframework.beans.factory.InitializingBean;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;

/**
 * 验证码实现
 *
 * @author deniro
 *         15-2-24上午11:05
 */
public class CaptchaServiceImpl implements CaptchaService, InitializingBean {
    /**
     * 验证码生成器
     */
    private DefaultKaptcha producer;
    private Map<String, String> captchaMap = new HashMap<String, String>();
    /**
     * 预定义验证码内容列表
     */
    private List<String> preDefinedTexts;
    /**
     * 预定义验证码内容列表索引
     */
    private int textCount = 0;

    /**
     * 生成随机验证码
     *
     * @return
     * @throws CaptchaException
     */
    @Override
    public String generateCaptchaKey() throws CaptchaException {
        String key = RandomGenerator.getRandomString();//主键的目的仅是标识验证码图片,本身没有实际意义
        String value = getCaptchaText();
        captchaMap.put(key, value);
        return key;
    }

    /**
     * 生成验证码字符串
     *
     * @return
     */
    private String getCaptchaText() {
        if (preDefinedTexts != null && !preDefinedTexts.isEmpty()) {//顺序循环字符串列表读取值
            String text = preDefinedTexts.get(textCount);
            textCount = (textCount + 1) % preDefinedTexts.size();
            return text;
        } else {//创建随机字符串
            return producer.createText();
        }
    }

    /**
     * 生成验证码图片
     *
     * @param captchaKey
     * @return
     * @throws CaptchaException
     */
    @Override
    public byte[] generateCaptchaImage(String captchaKey) throws CaptchaException {
        String text = captchaMap.get(captchaKey);
        if (text == null) {
            throw new CaptchaException("验证码' " + captchaKey + " ' 未找到。");
        }

        BufferedImage image = producer.createImage(text);
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        try {
            ImageIO.write(image, "jpg", out);
        } catch (Exception e) {
            throw new CaptchaException("无法生成验证码流。");
        }

        return out.toByteArray();
    }

    /**
     * 验证
     *
     * @param captchaKey
     * @param captchaValue
     * @return
     * @throws CaptchaException
     */
    @Override
    public boolean validateCaptcha(String captchaKey, String captchaValue) throws CaptchaException {
        String text = captchaMap.get(captchaKey);
        if (text == null) {
            throw new CaptchaException("验证码主键' " + captchaKey + " '不存在!");
        }

        if (text.equals(captchaValue)) {
            captchaMap.remove(captchaKey);
            return true;
        } else {
            return false;
        }
    }

    @Override
    public List<String> getPreDefinedTexts() {
        return preDefinedTexts;
    }

    @Override
    public void setPreDefinedTexts(List<String> preDefinedTexts) {
        this.preDefinedTexts = preDefinedTexts;
    }

    /**
     * 初始化验证码生成器,并提供默认配置
     * <p/>
     * Spring初始化对象时调用
     *
     * @throws Exception
     */
    @Override
    public void afterPropertiesSet() throws Exception {
        producer = new DefaultKaptcha();
        producer.setConfig(new Config(new Properties()));
    }
}

RandomGenerator:

package net.deniro.captcha;

import java.util.Random;

/**
 * 随机码生成器
 *
 * @author deniro
 *         15-2-24上午10:59
 */
public class RandomGenerator {
    /**
     * 字符范围
     */
    private static String range="0123456789abcdefghijklmnopqrstuvwxyz";

    /**
     * 获取随机字符串
     *
     * 静态、线程安全
     * @return
     */
    public static synchronized String getRandomString(){
        Random random=new Random();
        StringBuilder result=new StringBuilder();
        for (int i = 0; i < 8; i++) {
            result.append(range.charAt(random.nextInt(range.length())));
        }
        return result.toString();
    }
}

CaptchaException:

package net.deniro.captcha;

/**
 * 验证码异常
 *
 * @author deniro
 *         15-2-24上午10:51
 */
public class CaptchaException extends Exception {

    public CaptchaException(String message) {
        super(message);
    }

    public CaptchaException(String message, Throwable throwable) {
        super(message, throwable);
    }
}

captcha.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="CaptchaService" class="net.deniro.captcha.CaptchaServiceImpl"></bean>

</beans>

CaptchaServiceTest:

package captcha;

import net.deniro.captcha.CaptchaService;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;

import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;

/**
 * @author deniro
 *         15-2-24下午11:24
 */
public class CaptchaServiceTest {

    private CaptchaService service;

    @Before
    public void prepare() throws Exception {
        ApplicationContext ctx = new ClassPathXmlApplicationContext("captcha.xml");
        service = (CaptchaService) ctx.getBean("CaptchaService");
    }

    @Test
    public void testGenerateCaptcha() throws Exception {
        List<String> preDefinedTexts = new ArrayList<String>();
        preDefinedTexts.add("12345");
        preDefinedTexts.add("abcde");
        service.setPreDefinedTexts(preDefinedTexts);

        for (int i = 0; i < preDefinedTexts.size(); i++) {

            String captchaKey = service.generateCaptchaKey();
            assertNotNull(captchaKey);

            byte[] captchaImage = service.generateCaptchaImage(captchaKey);
            assertTrue(captchaImage.length > 0);

            File image = new File("target/" + captchaKey + ".jpg");
            OutputStream output = null;
            try {
                output = new FileOutputStream(image);
                output.write(captchaImage);
            } finally {
                if (output != null) {
                    output.close();
                }
            }
            assertTrue(image.exists() && image.length() > 0);
        }

    }

    @Test
    public void testValidateCaptchaCorrect() throws Exception {

        List<String> preDefinedTexts = new ArrayList<String>();
        preDefinedTexts.add("12345");
        preDefinedTexts.add("abcde");
        service.setPreDefinedTexts(preDefinedTexts);

        String captchaKey = service.generateCaptchaKey();
        service.generateCaptchaImage(captchaKey);
        assertTrue(service.validateCaptcha(captchaKey, "12345"));

        captchaKey = service.generateCaptchaKey();
        service.generateCaptchaImage(captchaKey);
        assertTrue(service.validateCaptcha(captchaKey, "abcde"));
    }
}

生成的验证码图片:

时间: 2024-10-10 08:37:08

验证码功能实现的相关文章

java web中图片验证码功能实现

用户在注册网站信息的时候基本上都要数据验证码验证.那么图片验证码功能该如何实现呢? 大概步骤是: 1.在内存中创建缓存图片 2.设置背景色 3.画边框 4.写字母 5.绘制干扰信息 6.图片输出 废话不多说,直接上代码 package com.lsgjzhuwei.servlet.response; import java.awt.Color; import java.awt.Font; import java.awt.Graphics; import java.awt.image.Buffer

使用thinkphp3.2中的验证码功能

为了网站的安全性,使用验证码技术是比较常见的,今天按照thinkphp3.2完全开发手册的例子试了一下(地址http://document.thinkphp.cn/manual_3_2.html#verify),总是报错,没法显示验证码,原因原来是在PHP.INI文件中没有打开GD库. 只要将配置文件PHP.INI中的extension=php_gd2.dll注释去掉就可以了(php_gd2.dll   GD 库图像函数库 GD2). 生成验证码 public function code() {

简单 验证码 功能

在贴代码之前首先简述一下验证验证码原理:随机获取验证码的值,把这个值存到session中,其作用可想而知就是要拿来跟前台数据作比较,通过Graphics将值进行模糊处理之后传到前台页面展示. 1 package com.skss.util; 2 3 4 import java.awt.Color; 5 import java.awt.Font; 6 import java.awt.Graphics; 7 import java.awt.image.BufferedImage; 8 import

验证码功能

验证码功能 ① 在Public控制器中定义verify方法 ② 设置验证码相关参数 codeSet:显示的字符串 useZh:是否使用中文验证码 zhSet:显示的中文字符串 useImgBg:是否使用图片背景 fontSize:字体大小 useCurve:是否使用混淆线 useNoise:是否使用杂点 length:验证码采用多少个字符 fontttf:使用的字体样式 ③ 中文验证码 运行结果: 为什么会出现以上问题? 答:因为还没有提供任何中文字体,必须到系统字体目录中复制黑体常规到Thin

使用JS来实现验证码功能

最近想为自己的Django博客添加验证码功能,本来想使用第三方库来实现的,不过考虑到添加第三方库对性能的影响,以及第三方库是否安全可靠的问题,还是用自己的代码来实现吧.反正用JS来实现验证码功能又不是很难. 简单来说,用一个create_code()方法在页面中生成验证码,然后control_submit()方法检测验证码文本框(id="user_input_code")的键盘输入事件,当文本框输入了超过4个字符后,调用verify_code ()检测输入的字符与生成的验证码是否一致,

JavaScript 实现验证码功能

1.编写用户登录界面 根据需要自行完成,参见用户注册与登录设计. 2.编写实现验证码JavaScript脚本 <head> <script language="javascript" type="text/javascript"> var code ; //在全局 定义验证码 function createCode(){   //产生验证码函数 code = new Array(); var codeLength = 4;//验证码的长度 v

自己实现一个验证码功能

用Servlet技术实现验证码功能,(画出一个验证码) 公司中一般用写好的验证码(jar包),很少使用自己去画验证码 . package chensi.com; import java.awt.Color; import java.awt.Font; import java.awt.Graphics; import java.awt.image.BufferedImage; import java.io.IOException; import java.util.Random; import j

thinkphp验证码功能

Think\Verify类可以支持验证码的生成和验证功能. 为了显示这个验证码功能,第一要有控制器,再就是有方法,然后是显示的页面. 一.最简单的方式生成验证码 (1)我们还是继续在那个控制器编写方法 这个方法显示这个验证码的页面 public function xianshi() { $this->show(); } public function shengcheng() { //造验证码的对象 $v = new \Think\Verify(); //生成验证码 $v->entry();

Php实现验证码功能

验证码这样的功能可以说是无处不在了,接下来使用php来实现验证码这样的功能,这里我是将验证码实现抽取到一个类中独立开来,那么后面如果再使用到验证码功能,直接引入该类文件并创建该类的实例,就可以使用验证码了,代码如下: 验证码类文件vcode.class.php <?php /** *验证码类 */ class Vcode{ private $width;//图片宽度 private $height;//图片高度 private $num;//验证码个数 private $img;//图片资源 p

页面实现验证码功能,点击“注册”按钮后,无论是否完成注册,验证码都能够自动刷新

要求页面实现验证码功能,点击"注册"按钮后,无论是否完成注册,验证码都能够自动刷新 <script> function validteCode() { var codes = new Array(4);       // var colors = new Array("Red","Green","Gray","Blue","Maroon","Aqua",&