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 |