Java实现验证码制作

验证码概述

验证码(CAPTCHA)是是一种区分用户是计算机还是人的公共全自动程序。可以防止:恶意破解密码、刷票、论坛灌水,有效防止对某一个特定注册用户用特定程序暴力破解方式进行不断的登陆尝试。

自定义实现方式

1、引入pom文件

    <!-- servlet、jsp、jstl -->
    <dependency>
        <groupId>javax.servlet.jsp</groupId>
        <artifactId>jsp-api</artifactId>
        <version>2.2</version>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>servlet-api</artifactId>
        <version>2.5</version>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>javax.servlet.jsp.jstl</groupId>
        <artifactId>jstl-api</artifactId>
        <version>1.2</version>
    </dependency>

2、写servlet和配置web.xml

/**
 * 自定义验证码
 */
public class ImageServlet extends HttpServlet{
    //图片宽
    private static final int WIDTH = 68;
    //图片高
    private static final int HEIGHT = 22;

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        BufferedImage bi = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
        Graphics graphics = bi.getGraphics();
        Color color = new Color(200,150,255);
        graphics.setColor(color);
        graphics.fillRect(0, 0, WIDTH, HEIGHT);
        char[] ch = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789".toCharArray();
        Random random = new Random();
        int len = ch.length;
        int index;
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < 4; i++) {
            index = random.nextInt(len);
            graphics.setColor(new Color(random.nextInt(88), random.nextInt(188), random.nextInt(255)));
            graphics.drawString(ch[index]+"", (i*15)+3, 18);
            sb.append(ch[index]);
        }
        req.getSession().setAttribute("authCode", sb.toString());
        ImageIO.write(bi, "JPG", resp.getOutputStream());
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}

/**
 * 登录验证
 */
public class LoginServlet extends HttpServlet{

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html;charset=utf-8");
        String authCode = (String) req.getSession().getAttribute("authCode");
        String checkCode = req.getParameter("checkCode");
        PrintWriter out = resp.getWriter();
        if (checkCode != null && checkCode.equalsIgnoreCase(authCode)) {
            //跳转登陆成功页面
            out.print("登陆成功!");
        }else{
            out.print("验证码输入错误!");
        }
        out.close();
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}

配置web.xml

 <servlet>
    <servlet-name>image</servlet-name>
    <servlet-class>cn.aric.auth.ImageServlet</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>image</servlet-name>
    <url-pattern>/ImageServlet</url-pattern>
  </servlet-mapping>
   <servlet>
    <servlet-name>login</servlet-name>
    <servlet-class>cn.aric.auth.LoginServlet</servlet-class>
  </servlet>

3、页面

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>首页</title>
<% 
    String path = request.getContextPath();
    String bathPath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort(); 
    pageContext.setAttribute("path", path);
    pageContext.setAttribute("bathPath", bathPath);
%>
<script type="text/javascript">
    function refreshCode(){
        var time = new Date().getTime();
        document.getElementById("imageCode").src = "${path}/ImageServlet?d="+time;
    }
</script>
</head>
<body>
    <form action="${path }/LoginServlet" method="post">
        验证码:<input type="text" name="checkCode" />
        <img alt="" name="imageCode" id="imageCode" src="${path }/ImageServlet" onclick="refreshCode();" />
        <a href="javascript:refreshCode()">看不清楚</a><br/>
        <input type="submit" value="登陆" />
    </form>
</body>
</html>

开源组件实现方式

  • Jcaptcha:用来生成图片验证码的Java开源组件,使用起来也是非常的简单方便。与Spring组合使用,可产生多种形式的验证码。
  • Kaptcha:可以生成各种样式的验证码,它是可配置的。
Jcaptcha

与spring整合使用,略。

Kaptcha

1、pom文件

    <!-- kaptcha验证码 -->
    <dependency>
        <groupId>com.github.axet</groupId>
        <artifactId>kaptcha</artifactId>
        <version>0.0.9</version>
    </dependency>

2、编写servlet,根据开发需求选择,配置web.xml

/**
 *kaptcha(字母数字组合验证)
 */
public class CheckServlet extends HttpServlet{

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html;charset=utf-8");
        PrintWriter out = resp.getWriter();
        //获取session中的验证码
        String kaptchaCode = req.getSession().getAttribute(com.google.code.kaptcha.Constants.KAPTCHA_SESSION_KEY)+"";
        //获取用户传递给后台的验证码
        String code = req.getParameter("code");
        if (code != null && code.equals(kaptchaCode)) {
            out.print("验证码正确!");
        }else {
            out.print("验证码错误!");
        }
        out.close();
    }
}

/**
 * 中文验证码
 */
public class ChineseCode extends Configurable implements TextProducer{

    public String getText() {
        int len = getConfig().getTextProducerCharLength();
        String finalWord = "",firstWord = "";
        int temp = 0;
        String[] arr = {"0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f"};
        Random r = new Random();
        for (int i = 0; i < len; i++) {
            switch (r.nextInt(arr.length)) {
            case 1:
                temp = r.nextInt(26) + 65;
                firstWord = String.valueOf(temp);
                break;
            case 2:
                int r1,r2,r3,r4;
                String strH,strL;
                r1 = r.nextInt(3) + 11;
                if (r1 == 13) {
                    r2 = r.nextInt(7);
                }else {
                    r2 = r.nextInt(16);
                }
                r3 = r.nextInt(6)+10;
                if (r3 == 10) {
                    r4 = r.nextInt(15) + 1;
                }else if (r3 == 15) {
                    r4 = r.nextInt(15);
                }else {
                    r4 = r.nextInt(16);
                }
                strH = arr[r1] + arr[r2];
                strL = arr[r3] + arr[r4];
                byte[] bytes = new byte[2];
                bytes[0] = (byte)Integer.parseInt(strH,16);
                bytes[1] = (byte)Integer.parseInt(strL,16);
                try {
                    firstWord = new String(bytes,"GBK");
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                }

                break;
            default:
                temp = r.nextInt(10) + 48;
                firstWord = String.valueOf((char)temp);
                break;
            }
            finalWord += firstWord;
        }
        return finalWord;
    }

}

/**
 * 算式验证码,覆盖原生KaptchaServlet
 */
@SuppressWarnings("serial")
public class KaptchaServlet extends HttpServlet implements Servlet
{
    private Properties props = new Properties();

    private Producer kaptchaProducer = null;

    private String sessionKeyValue = null;

    private String sessionKeyDateValue = null;

    @Override
    public void init(ServletConfig conf) throws ServletException
    {
        super.init(conf);

        // Switch off disk based caching.
        ImageIO.setUseCache(false);

        Enumeration<?> initParams = conf.getInitParameterNames();
        while (initParams.hasMoreElements())
        {
            String key = (String) initParams.nextElement();
            String value = conf.getInitParameter(key);
            this.props.put(key, value);
        }

        Config config = new Config(this.props);
        this.kaptchaProducer = config.getProducerImpl();
        this.sessionKeyValue = config.getSessionKey();
        this.sessionKeyDateValue = config.getSessionDate();
    }

    @Override
    public void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException
    {
        // Set standard HTTP/1.1 no-cache headers.
        resp.setHeader("Cache-Control", "no-store, no-cache");

        // return a jpeg
        resp.setContentType("image/jpeg");

        // create the text for the image
        String capText = this.kaptchaProducer.createText();
        //自定义算式验证码
        String s1 = capText.substring(0,1);
        String s2 = capText.substring(1,2);
        int value = Integer.valueOf(s1).intValue() + Integer.valueOf(s2).intValue();
        // create the image with the text
        BufferedImage bi = this.kaptchaProducer.createImage(s1+"+"+s2+"=?");
        ServletOutputStream out = resp.getOutputStream();
        // write the data out
        ImageIO.write(bi, "jpg", out);

        // store the text in the session
        req.getSession().setAttribute(this.sessionKeyValue, value);

        // their kaptcha
        req.getSession().setAttribute(this.sessionKeyDateValue, new Date());
        //关流,最好用finally
        out.close();
    }
}

配置web.xml

<servlet>
    <servlet-name>check</servlet-name>
    <servlet-class>cn.aric.auth.CheckServlet</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>check</servlet-name>
    <url-pattern>/CheckServlet</url-pattern>
  </servlet-mapping>

  <!-- kaptcha验证码 -->
  <servlet>
    <servlet-name>kaptcha</servlet-name>
    <!-- <servlet-class>com.google.code.kaptcha.servlet.KaptchaServlet</servlet-class> -->
    <!--算式验证码-->
    <servlet-class>cn.aric.auth.KaptchaServlet</servlet-class>
    <!--kaptcha自定义配置-->
    <init-param>
        <description>图片边框,合法值:yes , no</description>
        <param-name>kaptcha.border</param-name>
        <param-value>yes</param-value>
    </init-param>
    <init-param>
        <description>
            边框颜色,合法值: r,g,b (and optional alpha) 或者
            white,black,blue.
        </description>
        <param-name>kaptcha.border.color</param-name>
        <param-value>black</param-value>
    </init-param>
    <init-param>
        <description>边框厚度,合法值:>0</description>
        <param-name>kaptcha.border.thickness</param-name>
        <param-value>1</param-value>
    </init-param>
    <init-param>
        <description>图片宽 </description>
        <param-name>kaptcha.image.width</param-name>
        <param-value>200</param-value>
    </init-param>
    <init-param>
        <description>图片高 </description>
        <param-name>kaptcha.image.height</param-name>
        <param-value>50</param-value>
    </init-param>
    <init-param>
        <description>图片实现类</description>
        <param-name>kaptcha.producer.impl</param-name>
        <param-value>
            com.google.code.kaptcha.impl.DefaultKaptcha
        </param-value>
    </init-param>
    <init-param>
        <description>文本实现类</description>
        <param-name>kaptcha.textproducer.impl</param-name>
        <!-- 默认的文本实现类 -->
        <!-- <param-value>
            com.google.code.kaptcha.text.impl.DefaultTextCreator
        </param-value> -->
        <!-- 自定义中文文本实现类 -->
        <param-value>cn.aric.auth.ChineseCode</param-value>
    </init-param>
    <init-param>
        <description>文本集合,验证码值从此集合中获取</description>
        <param-name>kaptcha.textproducer.char.string</param-name>
        <!-- <param-value>0123456789</param-value> -->
        <param-value>ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789</param-value>
    </init-param>
    <init-param>
        <description>验证码长度 </description>
        <param-name>kaptcha.textproducer.char.length</param-name>
        <param-value>4</param-value>
    </init-param>
    <init-param>
        <description>字体 Arial, Courier</description>
        <param-name>kaptcha.textproducer.font.names</param-name>
        <param-value>Arial, Courier</param-value>
    </init-param>
    <init-param>
        <description>字体大小 40px.</description>
        <param-name>kaptcha.textproducer.font.size</param-name>
        <param-value>40</param-value>
    </init-param>
    <init-param>
        <description>
            字体颜色,合法值: r,g,b 或者 white,black,blue.
        </description>
        <param-name>kaptcha.textproducer.font.color</param-name>
        <param-value>black</param-value>
    </init-param>
    <init-param>
        <description>文字间隔 </description>
        <param-name>kaptcha.textproducer.char.space</param-name>
        <param-value>2</param-value>
    </init-param>
    <init-param>
        <description>干扰实现类</description>
        <param-name>kaptcha.noise.impl</param-name>
        <param-value>
            com.google.code.kaptcha.impl.DefaultNoise
        </param-value>
    </init-param>
    <init-param>
        <description>
            干扰颜色,合法值: r,g,b 或者 white,black,blue.
        </description>
        <param-name>kaptcha.noise.color</param-name>
        <param-value>black</param-value>
    </init-param>
    <init-param>
        <description>
            图片样式: 水纹com.google.code.kaptcha.impl.WaterRipple
            鱼眼com.google.code.kaptcha.impl.FishEyeGimpy
            阴影com.google.code.kaptcha.impl.ShadowGimpy
        </description>
        <param-name>kaptcha.obscurificator.impl</param-name>
        <param-value>
            com.google.code.kaptcha.impl.WaterRipple
        </param-value>
    </init-param>
    <init-param>
        <description>背景实现类</description>
        <param-name>kaptcha.background.impl</param-name>
        <param-value>
            com.google.code.kaptcha.impl.DefaultBackground
        </param-value>
    </init-param>
    <init-param>
        <description>背景颜色渐变,开始颜色</description>
        <param-name>kaptcha.background.clear.from</param-name>
        <param-value>green</param-value>
    </init-param>
    <init-param>
        <description>背景颜色渐变,结束颜色</description>
        <param-name>kaptcha.background.clear.to</param-name>
        <param-value>white</param-value>
    </init-param>
    <init-param>
        <description>文字渲染器</description>
        <param-name>kaptcha.word.impl</param-name>
        <param-value>
            com.google.code.kaptcha.text.impl.DefaultWordRenderer
        </param-value>
    </init-param>
    <init-param>
        <description>
            session中存放验证码的key键
        </description>
        <param-name>kaptcha.session.key</param-name>
        <param-value>KAPTCHA_SESSION_KEY</param-value>
    </init-param>
    <init-param>
        <description>
            The date the kaptcha is generated is put into the
            HttpSession. This is the key value for that item in the
            session.
        </description>
        <param-name>kaptcha.session.date</param-name>
        <param-value>KAPTCHA_SESSION_DATE</param-value>
    </init-param>
  </servlet>
  <servlet-mapping>
    <servlet-name>kaptcha</servlet-name>
    <url-pattern>/kaptcha.jpg</url-pattern>
  </servlet-mapping>

3、页面

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>首页</title>
<% 
    String path = request.getContextPath();
    String bathPath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort(); 
    pageContext.setAttribute("path", path);
    pageContext.setAttribute("bathPath", bathPath);
%>
</head>
<body>
<form action="${path }/CheckServlet" method="post">
    <img alt="" src="kaptcha.jpg">
    <input type="text" name="code" />
    <input type="submit" value="提交" />
</form>
</body>
</html>

图片验证码

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值