Jade Dungeon

Java 验证码

生成验证码

    import java.awt.Color;  
    import java.awt.Font;  
    import java.awt.Graphics2D;  
    import java.awt.image.BufferedImage;  
    import java.io.File;  
    import java.io.IOException;  
    import java.util.Random;  
      
    import javax.imageio.ImageIO;  
      
    import org.springframework.stereotype.Component;  
      
    /** 
     * CheckCode.java 
     *  
     * @author King<br/> 
     *          
     * @Description 验证码生成类 
     * @since 1.0.0 
     * @Date 2012-2-29下午1:50:25 
     */  
    @Component  
    public class CheckCode {  
        private int width = 102;  
        private int height = 28;  
        private int codeCount = 4;  
      
        private Random random = new Random();  
      
        /** 
         * 验证码图片 
         */  
        private BufferedImage buffImg;  
        /** 
         * 验证码字符串 
         */  
        private String checkCodeStr;  
      
        /** 
         *  
         * @Description:创建验证码对象 
         * @since 1.0.0 
         * @Date:2012-3-1 上午10:26:20 
         * @return CheckCode 
         */  
        public CheckCode createCheckCode() {  
            CheckCode checkCode = new CheckCode();  
            checkCode.setCheckCodeStr(createRandomCode());  
            checkCode.setBuffImg(disturb());  
            return checkCode;  
        }  
      
        /** 
         *  
         * @Description:随机产生的验证码 
         * @since 1.0.0 
         * @Date:2012-3-1 上午10:20:05 
         * @return String 
         */  
        private String createRandomCode() {  
            StringBuffer randomCode = new StringBuffer();  
      
            String strRand = null;  
            int xx = width / (codeCount + 1);  
            int codeY = height - 4;  
            char[] codeSequence = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J',  
                    'K', 'L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',  
                    'X', 'Y', 'Z', '2', '3', '4', '5', '6', '7', '8', '9' };  
      
            Graphics2D graphics = graphicsInit();  
            graphics.setColor(createColor());  
      
            for (int i = 0; i < codeCount; i++) {  
                strRand = String.valueOf(codeSequence[random.nextInt(32)]);  
                randomCode.append(strRand);  
      
                graphics.drawString(strRand, (i + 1) * xx, codeY);  
            }  
      
            return randomCode.toString();  
        }  
      
        /** 
         *  
         * @Description:创建颜色 
         * @since 1.0.0 
         * @Date:2012-2-29 下午4:47:14 
         * @return Color 
         */  
        private Color createColor() {  
            Color color[] = new Color[10];  
            color[0] = new Color(113, 31, 71);  
            color[1] = new Color(37, 0, 37);  
            color[2] = new Color(111, 33, 36);  
            color[3] = new Color(0, 0, 112);  
            color[4] = new Color(14, 51, 16);  
            color[5] = new Color(1, 1, 1);  
            color[6] = new Color(72, 14, 73);  
            color[7] = new Color(65, 67, 29);  
            color[8] = new Color(116, 86, 88);  
            color[9] = new Color(41, 75, 71);  
      
            return color[random.nextInt(10)];  
        }  
      
        /** 
         *  
         * @Description:绘制类初始化 
         * @since 1.0.0 
         * @Date:2012-3-1 上午10:17:52 
         * @return Graphics2D 
         */  
        private Graphics2D graphicsInit() {  
            Graphics2D graphics = buffImgInit().createGraphics();  
            graphics.setColor(Color.WHITE);  
            graphics.fillRect(0, 0, width, height);  
            graphics.setFont(new Font("Fixedsys", Font.BOLD, height - 2));  
            graphics.drawRect(0, 0, width - 1, height - 1);  
            return graphics;  
        }  
      
        /** 
         *  
         * @Description:BufferedImage初始化 
         * @since 1.0.0 
         * @Date:2012-3-1 上午11:07:18 
         * @return BufferedImage 
         */  
        private BufferedImage buffImgInit() {  
            buffImg = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);  
            return buffImg;  
        }  
      
        /** 
         *  
         * @Description:绘制干扰特性 
         * @since 1.0.0 
         * @Date:2012-3-1 上午11:45:32 
         * @return BufferedImage 
         */  
        private BufferedImage disturb() {  
            drawDisturbLine(buffImg.createGraphics());  
            return twistImage();  
        }  
      
        /** 
         *  
         * @Description:画干扰线使图象中的认证码不易被其它程序探测到 
         * @since 1.0.0 
         * @Date:2012-2-29 下午4:28:23 
         * @param graphics 
         *            void 
         */  
        private void drawDisturbLine(Graphics2D graphics) {  
            graphics.setColor(Color.BLACK);  
            int x = 0;  
            int y = 0;  
            int xl = 0;  
            int yl = 0;  
            for (int i = 0; i < 15; i++) {  
                x = random.nextInt(width);  
                y = random.nextInt(height);  
                xl = random.nextInt(20);  
                yl = random.nextInt(10);  
                graphics.drawLine(x, y, x + xl, y + yl);  
            }  
        }  
      
        /** 
         *  
         * @Description:正弦曲线Wave扭曲图片 
         * @since 1.0.0 
         * @Date:2012-3-1 下午12:49:47 
         * @return BufferedImage 
         */  
        private BufferedImage twistImage() {  
            double dMultValue = random.nextInt(7) + 3;// 波形的幅度倍数,越大扭曲的程序越高,一般为3  
            double dPhase = random.nextInt(6);// 波形的起始相位,取值区间(0-2*PI)  
      
            BufferedImage destBi = new BufferedImage(buffImg.getWidth(),  
                    buffImg.getHeight(), BufferedImage.TYPE_INT_RGB);  
      
            for (int i = 0; i < destBi.getWidth(); i++) {  
                for (int j = 0; j < destBi.getHeight(); j++) {  
                    int nOldX = getXPosition4Twist(dPhase, dMultValue,  
                            destBi.getHeight(), i, j);  
                    int nOldY = j;  
                    if (nOldX >= 0 && nOldX < destBi.getWidth() && nOldY >= 0  
                            && nOldY < destBi.getHeight()) {  
                        destBi.setRGB(nOldX, nOldY, buffImg.getRGB(i, j));  
                    }  
                }  
            }  
            return destBi;  
        }  
      
        /** 
         *  
         * @Description:获取扭曲后的x轴位置 
         * @since 1.0.0 
         * @Date:2012-3-1 下午3:17:53 
         * @param dPhase 
         * @param dMultValue 
         * @param height 
         * @param xPosition 
         * @param yPosition 
         * @return int 
         */  
        private int getXPosition4Twist(double dPhase, double dMultValue,  
                int height, int xPosition, int yPosition) {  
            double PI = 3.1415926535897932384626433832799; // 此值越大,扭曲程度越大  
            double dx = (double) (PI * yPosition) / height + dPhase;  
            double dy = Math.sin(dx);  
            return xPosition + (int) (dy * dMultValue);  
        }  
      
        /** 
         *  
         * @Description:将图像进行输出到文件 
         * @since 1.0.0 
         * @Date:2012-3-1 上午11:56:19 
         * @param pathName 
         * @return String 
         */  
        public String createImgFile(String pathName) {  
            File file = new File(pathName);  
            if (file.isFile() && file.exists()) {  
                file.delete();  
            }  
            try {  
                ImageIO.write(buffImg, "jpeg", file);  
            } catch (IOException e) {  
                e.printStackTrace();  
            }  
            return pathName;  
        }  
      
        public BufferedImage getBuffImg() {  
            return buffImg;  
        }  
      
        public void setBuffImg(BufferedImage buffImg) {  
            this.buffImg = buffImg;  
        }  
      
        public String getCheckCodeStr() {  
            return checkCodeStr;  
        }  
      
        public void setCheckCodeStr(String checkCodeStr) {  
            this.checkCodeStr = checkCodeStr;  
        }  
      
        public int getWidth() {  
            return width;  
        }  
      
        public void setWidth(int width) {  
            this.width = width;  
        }  
      
        public int getHeight() {  
            return height;  
        }  
      
        public void setHeight(int height) {  
            this.height = height;  
        }  
      
        public int getCodeCount() {  
            return codeCount;  
        }  
      
        public void setCodeCount(int codeCount) {  
            this.codeCount = codeCount;  
        }  
      
    }  

测试:

    import org.junit.Assert;  
    import org.junit.Test;  
      
    /** 
     * CheckCodeTest.java 
     * @author King<br/> 
     *         
     * @Description 描述一下这个文件 
     * @since 1.0.0 
     * @Date 2012-2-29下午1:51:13 
     */  
    public class CheckCodeTest {  
        @Test  
        public void testCheckCodeCreate(){  
            CheckCode checkCode=new CheckCode();  
              
            checkCode=checkCode.createCheckCode();  
            String checkCodeStr=checkCode.getCheckCodeStr();  
            System.out.println(checkCodeStr);  
            Assert.assertNotNull(checkCodeStr);  
            Assert.assertEquals(4, checkCodeStr.length());  
              
            Assert.assertNotNull(checkCode.getBuffImg());  
              
    //      for (int i = 0; i < 10; i++) {  
    //          checkCode=checkCode.createCheckCode();  
    //          String checkCodeStr=checkCode.getCheckCodeStr();  
    //          System.out.println(checkCodeStr);  
    //          Assert.assertNotNull(checkCodeStr);  
    //          Assert.assertEquals(4, checkCodeStr.length());  
    //            
    //          String filePathName="C:\\test"+i+".jpg";  
    //          checkCode.createImgFile(filePathName);  
    //          File file=new File(filePathName);  
    //            
    //          Assert.assertTrue(file.exists());  
    //      }  
        }  
    }  

第三方库kaptcha 实现验证码

kaptcha的作者很反感maven,他们不信任中央库。所以不支持maven。要自己搞maven包。

官网:https://code.google.com/p/kaptcha/

依赖:

<dependency>
	<groupId>com.jhlabs</groupId>
	<artifactId>filters</artifactId>
	<version>2.0.235-1</version>
</dependency>

kaptcha需要使用classifier指定JDK版本:

<dependency>
	<groupId>com.google.code.kaptcha</groupId>
	<artifactId>kaptcha</artifactId>
	<version>2.3</version>
	<classifier>jdk15</classifier>
</dependency>
DefaultKaptcha productor = new DefaultKaptcha();
productor.setConfig(new Config(new Properties()));

BufferedImage image = productor.createImage("Hello World");
ByteArrayOutputStream out = new ByteArrayOutputStream();
ImageIO.write(image, "jpg", out);
byte[] imageData = out.toByteArray();

File imageFile = new File(this.imgTag + "kaptcha.jpg");
OutputStream os = null;
try {
	os = new FileOutputStream(imageFile);
	os.write(imageData);
} catch (Exception e) {
	throw e;
} finally {
	if (null != os) {
		os.close();
	}
}

配置参数

Configuration is done through web.xml. All values can be left blank and a default value will be chosen.

Below is an example of the init-param you would add to your web.xml. If you want to set other variables, then you would add more init-param blocks.

<init-param>
    <param-name>kaptcha.border</param-name>
    <param-value>yes</param-value>
</init-param>

Note: This only works with the KaptchaServlet. SimpleServlet does not pay attention to the web.xml parameters.

Details

These values are stored in the com.google.code.kaptcha.Constants class.

Constant Description Default
kaptcha.border Border around kaptcha. Legal values are yes or no. yes
kaptcha.border.color Color of the border. Legal values are r,g,b (and optional alpha) or white,black,blue. black
kaptcha.border.thickness Thickness of the border around kaptcha. Legal values are > 0. 1
kaptcha.image.width Width in pixels of the kaptcha image. 200
kaptcha.image.height Height in pixels of the kaptcha image. 50
kaptcha.producer.impl The image producer. com.google.code.kaptcha.impl.DefaultKaptcha
kaptcha.textproducer.impl The text producer. com.google.code.kaptcha.text.impl.DefaultTextCreator
kaptcha.textproducer.char.string The characters that will create the kaptcha. abcde2345678gfynmnpwx
kaptcha.textproducer.char.length The number of characters to display. 5
kaptcha.textproducer.font.names A list of comma separated font names Arial, Courier
kaptcha.textproducer.font.size The size of the font to use. 40px.
kaptcha.textproducer.font.color The color to use for the font. Legal values are r,g,b. black
kaptcha.textproducer.char.space The space between the characters 2
kaptcha.noise.impl The noise producer. com.google.code.kaptcha.impl.DefaultNoise
kaptcha.noise.color The noise color. Legal values are r,g,b. black
kaptcha.obscurificator.impl The obscurificator implementation. com.google.code.kaptcha.impl.WaterRipple
kaptcha.background.impl The background implementation. com.google.code.kaptcha.impl.DefaultBackground
kaptcha.background.clear.from Starting background color. Legal values are r,g,b. light grey
kaptcha.background.clear.to Ending background color. Legal values are r,g,b. white
kaptcha.word.impl The word renderer implementation. com.google.code.kaptcha.text.impl.DefaultWordRenderer
kaptcha.session.key The value for the kaptcha is generated and is put into the HttpSession. This is the key value for that item in the session. KAPTCHA_SESSION_KEY
kaptcha.session.date The date the kaptcha is generated is put into the HttpSession. This is the key value for that item in the session. KAPTCHA_SESSION_DATE