• Java 验证码生成工具(简单实现)


    在使用Java开发Web应用程序特别是时,经常要用到验证码,特别是在注册新用户、登录时,大量地使用到验证码;

    好的验证码可以有效的防止黑客使用机器人恶意登录,总之对于系统的安全是有很大影响的,以下为本人在平时开发项目的过程中总结出来的一个简单的验证码生成工具,原理很简单,只有一个类;

     

    下面进入正题:

    step1  在MyEclipse中新建一个web项目,在这里取名为ImageUtil,并在src目录下新建一个类 ImageUtil.java

    image

     

    step2  ImageUtil.java代码如下:

    复制代码
    package util;
    
    import java.awt.Color;
    import java.awt.Font;
    import java.awt.Graphics;
    import java.awt.image.BufferedImage;
    import java.io.ByteArrayInputStream;
    import java.io.ByteArrayOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.util.HashMap;
    import java.util.Map;
    import java.util.Random;
    
    import com.sun.image.codec.jpeg.JPEGCodec;
    import com.sun.image.codec.jpeg.JPEGImageEncoder;
    
    /**
     * 简单验证码生成工具
     * ImageUtil, 用于生成验证码
     * createImage方法返回一个Map类型,Map 的key是所生产的验证码的字符串,
     * Map的value是所生产的BufferImage类型的验证码;
     * getInputStream方法将 BufferImage转成InputStream类型;
     * @author CayZlh
     * @date 2013-11-26
     */
    public class ImageUtil {
        private static final char[] chars = {'0','1','2','3','4','5','6','7','8','9',
            'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
            'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H',
            'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'};
        private static final int SIZE = 4;            //字符数
        private static final int LINES = 12;        //干扰线数量
        private static final int WIDTH = 100;        //生成的验证码图片的宽度
        private static final int HEIGHT = 60;        //生成的验证码图片的长度
        private static final int FONT_SIZE = 35;    //字体大小
    
        public static Map<String, BufferedImage> createImage(){
            //用户保存字符串
            StringBuffer sb = new StringBuffer();
            //BufferImage类型的验证码
            BufferedImage image = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
            //获得画笔 
            Graphics g = image.getGraphics();
            g.setColor(Color.LIGHT_GRAY);    //设置背景色
            g.fillRect(0, 0, WIDTH, HEIGHT);//将背景色填充到图片中
            Random ran = new Random();    //获得一个Random对象
            
            //画字符
            for(int i=1; i<=SIZE; i++){
                int r = ran.nextInt(chars.length);    //得到一个随机的下标, chars 是保存着若干字符的char字符
                g.setColor(getRandomColor());        //得到一个随机的颜色
                g.setFont(new Font(null, Font.BOLD+Font.ITALIC, FONT_SIZE));    //设置字体大小
                g.drawString(chars[r]+"", (i-1)*WIDTH/SIZE, (int)(HEIGHT*0.7));    //画字符
                sb.append(chars[r]);
            }
            
            //画干扰线
            for(int i=1; i<=LINES; i++){
                g.setColor(getRandomColor());    //同样,干扰线也是用随机的颜色
                g.drawLine(ran.nextInt(WIDTH), ran.nextInt(HEIGHT), 
                        ran.nextInt(WIDTH), ran.nextInt(HEIGHT));//随机设置干扰线的方向
            }
            
            //将图片中的字符串保存为Map对象的key,BufferedImage保存为value
            Map<String, BufferedImage> map = new HashMap<String, BufferedImage>();    
            map.put(sb.toString(), image);
            return map;
        }
    
        /**
         * 获得一个随机的颜色 返回 Color对象
         * @return
         */
        private static Color getRandomColor() {
            Random ran = new Random();
            Color color = new Color(ran.nextInt(256), ran.nextInt(256), ran.nextInt(256)); 
            return color;
        }
    
        /**
         * 将 BufferImage转成InputStream类型
         * @param image
         * @return
         * @throws IOException
         */
        public static InputStream getInputStream(BufferedImage image) throws IOException{
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(bos);
            encoder.encode(image);
            byte[] imageBts = bos.toByteArray();
            InputStream in = new ByteArrayInputStream(imageBts);
            return in;
        }
    }
    复制代码

    到此为止,ImageUtil工具类算是写完了。

     

    接下来,就是去测试一下这个工具类的可用性了, 这部分我以Struts2为例展示一下效果,导入Struts2开发的jar包,新建Action类:

    image

     

    ImageDemoAction.java代码如下:

    复制代码
    package action;
    
    import java.awt.image.BufferedImage;
    import java.io.IOException;
    import java.io.InputStream;
    import java.util.Map;
    
    import util.ImageUtil;
    
    public class ImageDemoAction {
        
        //stream result只能输出InputStream类型
        private InputStream imageStream;
    
        public InputStream getImageStream() {
            return imageStream;
        }
    
        public void setImageStream(InputStream imageStream) {
            this.imageStream = imageStream;
        }
        
        public String execute() throws IOException{
            //生成验证码
            Map<String, BufferedImage> map = ImageUtil.createImage();
            String key = map.keySet().iterator().next();
            BufferedImage image = map.get(key);
            imageStream = ImageUtil.getInputStream(image);
            return "success";
        }
    }
    复制代码

    step3  添加Struts配置文件:

    复制代码
    <?xml version="1.0" encoding="UTF-8" ?>
    
    <!DOCTYPE struts PUBLIC
        "-//Apache Software Foundation//DTD Struts Configuration 2.1.7//EN"
        "http://struts.apache.org/dtds/struts-2.1.7.dtd">
    
    <struts>
      <package name="demo" extends="struts-default" namespace="/demo">
          <action name="image" class="action.ImageDemoAction">
                <!-- 
                    inputName是固定写法, 目的是给这种类型的Result对象的inputName属性赋值.
                    imageStream是Action里的输出属性名, 这个输出属性是InputStream类型的
                 -->
                <result type="stream">
                    <param name="inputName">imageStream</param>
                </result>
            </action>
      </package>
    
    </struts>
    复制代码

    该注意的地方在注释部分也有给出

     

      step4  配置web.xml:

        web.xml的配置比较简单,就配置一个过滤器就行

    复制代码
    <?xml version="1.0" encoding="UTF-8"?>
    <web-app version="2.5" 
        xmlns="http://java.sun.com/xml/ns/javaee" 
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
        xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
        http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
      <filter>
        <filter-name>Struts2</filter-name>
        <filter-class>
        org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter
        </filter-class>
      </filter>
      <filter-mapping>
        <filter-name>Struts2</filter-name>
        <url-pattern>/*</url-pattern>
      </filter-mapping>
    </web-app>
    复制代码

     

      step5  添加demo.jsp页面(需要引入jquery文件, 这里使用 jquery-1.4.3.js 版本,个人觉得这个版本是最好用的):

    复制代码
    <%@ 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>demo</title>
    <script type="text/javascript" src="js/jquery-1.4.3.js"></script>
            <script type="text/javascript">
                $(function(){
                    //为图片绑定单击事件
                    $('#imageCode').click(function(){
                        //设置src属性为action的参数为当前时间,保证验证码点击之后可以变换
                        $(this).attr('src', 'demo/image.action?dt=' + new Date().getTime());
                    });
                });
            </script> 
    </head>
    <body>
        <img src="demo/image.action" width="70" height="30"
                         alt="验证码" title="点击更换" id="imageCode" style="cursor: pointer;" />
    </body>
    </html>
    复制代码

     

      step6  部署并启动服务器,在浏览器查看效果:

      image

     

    点击图片,可以更换图片。

     

    image

     

    项目整体结构如下:

    image

     

    这个工具可以直接应用到各种web项目中,如果不是用Struts,也可以使用servlet转发到页面中。

        源代码下载地址 https://files.cnblogs.com/cayzlh/ImageUtil.zip

    有表达和技术不足的地方,欢迎指正。。。

  • 相关阅读:
    30 Day Challenge Day 11 | Leetcode 55. Jump Game
    30 Day Challenge Day 11 | Leetcode 11. Container With Most Water
    30 Day Challenge Day 10 | Leetcode 701. Insert into a Binary Search Tree
    30 Day Challenge Day 10 | Leetcode 1. Two Sum
    30 Day Challenge Day 10 | Leetcode 3. Longest Substring Without Repeating Characters
    30 Day Challenge Day 9 | Leetcode 425. Word Squares
    30 Day Challenge Day 8 | Leetcode 200. Number of Islands
    30 Day Challenge Day 7 | Leetcode 235. Lowest Common Ancestor of a Binary Search Tree
    30 Day Challenge Day 7 | Hackerrank: Tree: Huffman Decoding
    30 Day Challenge Day 6 | Leetcode 92. Reverse Linked List II
  • 原文地址:https://www.cnblogs.com/ustc-cui/p/3445181.html
Copyright © 2020-2023  润新知