为了防止,页面向数据库暴力注册入力,用户登录暴力破解,所以加入验证码,验证码无法被软件获取上边的内容(加入算数计算,更加安全),所以在现在技术,暂时安全。
先看效果图:
第一次加载比较慢,防止无法加载验证码显示,后台获取准备好的默认正在加载图片(静态图片),后台图片获取好后,替代。
验证码效果图:
后台Java图片实现类VerificationCodeTool:
package com.tsXs.fileshare.tools; import java.awt.Color; import java.awt.Font; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.image.BufferedImage; import java.util.HashMap; import java.util.Map; import java.util.Random; import org.apache.log4j.Logger; /** * * ClassName: VerificationCodeTool <br/> * Description: creat verification code <br/> * Date: 2015-3-3 下午08:37:55 <br/> * <br/> * * @author yptian@aliyun.com * * first made * @version 1.0.0<br/> * */ public class VerificationCodeTool { //LOG private static final Logger LOG =Logger.getLogger(VerificationCodeTool.class); //verification code image width private static final int IMG_WIDTH=146; //verification code image height private static final int IMG_HEIGHT=30; //The number of interference lines private static final int DISTURB_LINE_SIZE = 15; //generate a random number private Random random = new Random(); //result private int xyresult; //result random string private String randomString; //Chinese Numbers // private static final String [] CNUMBERS = \"零,一,二,三,四,五,六,七,八,九,十\".split(\",\"); //零一二三四五六七八九十乘除加减 //Here, must be java Unicode code private static final String CVCNUMBERS = \"\\u96F6\\u4E00\\u4E8C\\u4E09\\u56DB\\u4E94\\u516D\\u4E03\\u516B\\u4E5D\\u5341\\u4E58\\u9664\\u52A0\\u51CF\"; //Definition of drawings in the captcha characters font, font name, font style, font size //static final font : In Chinese characters garbled private final Font font = new Font(\"黑体\", Font.BOLD, 18); //data operator private static final Map<String, Integer> OPMap = new HashMap<String, Integer>(); static{ OPMap.put(\"*\", 11); OPMap.put(\"/\", 12); OPMap.put(\"+\", 13); OPMap.put(\"-\", 14); } /** * The generation of image verification code * */ public BufferedImage drawVerificationCodeImage(){ //image BufferedImage image = new BufferedImage(IMG_WIDTH, IMG_HEIGHT, BufferedImage.TYPE_INT_RGB); //In memory to create a brush Graphics g = image.getGraphics(); //Set the brush color // g.setColor(getRandomColor(200,250)); g.setColor(Color.WHITE); //Fill the background color, using the current brush colour changing background color images //The meaning of the four parameters respectively, starting x coordinates, starting y, width, height. //image background g.fillRect(0, 0, IMG_WIDTH, IMG_HEIGHT); //Set the brush color g.setColor(getRandomColor(200,250)); //image border g.drawRect(0, 0, IMG_WIDTH-2, IMG_HEIGHT-2); //Set disturb line color g.setColor(getRandomColor(110, 133)); //Generate random interference lines for(int i =0;i < DISTURB_LINE_SIZE; i++){ drawDisturbLine1(g); drawDisturbLine2(g); } //Generate a random number, set return data getRandomMathString(); LOG.info(\"验证码 : \"+randomString); LOG.info(\"验证码结果 : \"+xyresult); //The generated random string used to save the system StringBuffer logsu = new StringBuffer(); for(int j=0,k = randomString.length(); j < k; j++){ int chid = 0; if(j==1){ chid = OPMap.get(String.valueOf(randomString.charAt(j))); }else{ chid = Integer.parseInt(String.valueOf(randomString.charAt(j))); } String ch = String.valueOf(CVCNUMBERS.charAt(chid)); logsu.append(ch); drawRandomString((Graphics2D)g,ch, j); } //= ? drawRandomString((Graphics2D)g,\"\\u7B49\\u4E8E\\uFF1F\", 3); logsu.append(\"\\u7B49\\u4E8E \\uFF1F\"); LOG.info(\"汉字验证码 : \"+logsu); randomString = logsu.toString(); //Release the brush object g.dispose(); return image; } /** * Get a random string * */ private void getRandomMathString(){ //Randomly generated number 0 to 10 int xx = random.nextInt(10); int yy = random.nextInt(10); //save getRandomString StringBuilder suChinese = new StringBuilder(); //random 0,1,2 int Randomoperands = (int) Math.round(Math.random()*2); //multiplication if(Randomoperands ==0){ this.xyresult = yy * xx; // suChinese.append(CNUMBERS[yy]); suChinese.append(yy); suChinese.append(\"*\"); suChinese.append(xx); //division, divisor cannot be zero, Be divisible }else if(Randomoperands ==1){ if(!(xx==0) && yy%xx ==0){ this.xyresult = yy/xx; suChinese.append(yy); suChinese.append(\"/\"); suChinese.append(xx); }else{ this.xyresult = yy + xx; suChinese.append(yy); suChinese.append(\"+\"); suChinese.append(xx); } //subtraction }else if(Randomoperands ==2){ this.xyresult = yy - xx; suChinese.append(yy); suChinese.append(\"-\"); suChinese.append(xx); //add }else{ this.xyresult = yy + xx; suChinese.append(yy); suChinese.append(\"+\"); suChinese.append(xx); } this.randomString = suChinese.toString(); } /** * Draw a random string * @param g Graphics * @param randomString random string * @param i the random number of characters * */ public void drawRandomString(Graphics2D g,String randomvcch,int i){ //Set the string font style g.setFont(font); //Set the color string int rc = random.nextInt(255); int gc = random.nextInt(255); int bc = random.nextInt(255); g.setColor(new Color(rc, gc, bc)); //random string //Set picture in the picture of the text on the x, y coordinates, random offset value int x = random.nextInt(3); int y = random.nextInt(2); g.translate(x, y); //Set the font rotation angle int degree = new Random().nextInt() % 15; //Positive point of view g.rotate(degree * Math.PI / 180, 5+i*25, 20); //Character spacing is set to 15 px //Using the graphics context of the current font and color rendering by the specified string for a given text. //The most on the left side of the baseline of the characters in the coordinate system of the graphics context (x, y) location //str- to draw string.x - x coordinate.y - y coordinate. g.drawString(randomvcch, 5+i*25, 20); //Reverse Angle g.rotate(-degree * Math.PI / 180, 5+i*25, 20); } /** *Draw line interference *@param g Graphics * */ public void drawDisturbLine1(Graphics g){ int x1 = random.nextInt(IMG_WIDTH); int y1 = random.nextInt(IMG_HEIGHT); int x2 = random.nextInt(13); int y2 = random.nextInt(15); //x1 - The first point of the x coordinate. //y1 - The first point of the y coordinate //x2 - The second point of the x coordinate. //y2 - The second point of the y coordinate. //X1 and x2 is the starting point coordinates, x2 and y2 is end coordinates. g.drawLine(x1, y1, x1 + x2, y1 + y2); } /** *Draw line interference *@param g Graphics * */ public void drawDisturbLine2(Graphics g){ int x1 = random.nextInt(IMG_WIDTH); int y1 = random.nextInt(IMG_HEIGHT); int x2 = random.nextInt(13); int y2 = random.nextInt(15); //x1 - The first point of the x coordinate. //y1 - The first point of the y coordinate //x2 - The second point of the x coordinate. //y2 - The second point of the y coordinate. //X1 and x2 is the starting point coordinates, x2 and y2 is end coordinates. g.drawLine(x1, y1, x1 - x2, y1 - y2); } /** * For random color * @param fc fc * @param bc bc * @return color random color * */ public Color getRandomColor(int fc,int bc){ if(fc > 255){ fc = 255; } if(bc > 255){ bc = 255; } //Generate random RGB trichromatic int r = fc+random.nextInt(bc -fc - 16); int g = fc+random.nextInt(bc - fc - 14); int b = fc+random.nextInt(bc - fc - 18); return new Color(r, g, b); } /** * xyresult.<br/> * * @return the xyresult <br/> * */ public int getXyresult() { return xyresult; } /** * randomString.<br/> * * @return the randomString <br/> * */ public String getRandomString() { return randomString; } }
生产静态验证码(为了防止,加载慢,空白显示):
package com.tsXs.fileshare.tools; import java.awt.Color; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.image.BufferedImage; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileOutputStream; import javax.imageio.ImageIO; import javax.swing.ImageIcon; import javax.swing.filechooser.FileSystemView; import org.apache.log4j.Logger; import com.tsXs.fileshare.configuration.properties.StaticConstants; /** * ClassName: ImageTool <br/> * Description: get BufferedImage creat image<br/> * Date: 2015-3-10 下午05:05:38 <br/> * <br/> * * @author yptian@aliyun.com * * first made * @version 1.0.0<br/> * */ public class ImageTool { //LOG private static final Logger LOG = Logger.getLogger(ImageTool.class); //image private BufferedImage image; /** * createImage : out dest path for image * @param fileLocation dest path */ private void createImage(String fileLocation) { try { FileOutputStream fos = new FileOutputStream(fileLocation); BufferedOutputStream bos = new BufferedOutputStream(fos); ImageIO.write(image, \"png\", bos); // com.sun.image.codec.jpeg.JPEGImageEncoder encoder = com.sun.image.codec.jpeg.JPEGCodec.createJPEGEncoder(bos); // encoder.encode(image); bos.flush(); bos.close(); LOG.info(\"@2\"+fileLocation+\"图片生成输出成功\"); } catch (Exception e) { LOG.info(\"@2\"+fileLocation+\"图片生成输出失败\",e); } } /** * createFileIconImage :create share file list icon * @param destOutPath create file icon save dictory */ public void createFileIconImage(String destOutPath){ //get properties operate tool PropertiesTool propertiesTool = PropertiesTool.getInstance(StaticConstants.SHARE_FILE_CONFGURATION_PROPERTIES_PATH); //get share file root path String shareFileRootPath = propertiesTool.getPropertiesValue(\"FileShareRootPath\"); //root dictory File rootDictory = new File(shareFileRootPath); //child file list File [] fileList = rootDictory.listFiles(); //child list files File file = null; if(fileList != null && fileList.length>0){ LOG.info(\"分享文件根目录下文件数:\"+fileList.length); for(int i = 0,j = fileList.length;i < j;i++){ String fileName = fileList[i].getName(); String fileAllName = shareFileRootPath +fileName; file = new File(fileAllName); //get file system icon ImageIcon fileIcon = (ImageIcon) FileSystemView.getFileSystemView().getSystemIcon(file); image = (BufferedImage) fileIcon.getImage(); if(image != null){ LOG.info(\"@1\"+fileName+\"文件的图标获取成功\"); } Graphics g = image.getGraphics(); g.drawImage(image, 0, 0, null); String fileNameX = fileName.substring(0,fileName.lastIndexOf(\".\")); //out image to dest createImage(destOutPath+\"\\\\\"+fileNameX+\".png\"); LOG.info(\"@3\"+fileName+\"文件的图标生成成功\"); } } } /** * creatDefaultVerificationCode :create default verification code * @param destOutPath create creatDefaultVerificationCode save dictory */ public void creatDefaultVerificationCode(String destOutPath){ //verification code image height //comment to com.tss.fileshare.tools.VerificationCodeTool 65 row,please int imgwidth=146; int imgheight=30; int disturblinesize = 15; VerificationCodeTool vcTool = new VerificationCodeTool(); //default verification code image = new BufferedImage(imgwidth, imgheight, BufferedImage.TYPE_INT_RGB); Graphics g = image.getGraphics(); g.setColor(Color.WHITE); g.fillRect(0, 0, 146, 30); g.setColor(vcTool.getRandomColor(200,250)); g.drawRect(0, 0, imgwidth-2, imgheight-2); for(int i =0;i < disturblinesize; i++){ vcTool.drawDisturbLine1(g); vcTool.drawDisturbLine2(g); } //玩命加载中… String defaultVCString = \"\\u73A9\\u547D\\u52A0\\u8F7D\\u4E2D\\u2026\"; String dfch = null; for(int i = 0;i < 6;i++){ dfch = String.valueOf(defaultVCString.charAt(i)); vcTool.drawRandomString((Graphics2D)g, dfch, i); } LOG.info(\"默然验证码生成成功\"); // Graphics gvc = imagevc.getGraphics(); createImage(destOutPath+\"\\\\defaultverificationcode.jpeg\"); } /** * graphicsGeneration : create image * @param imgurl display picture url . eg:F:/imagetool/7.jpg<br/> * @param imageOutPathName image out path+naem .eg:F:\\\\imagetool\\\\drawimage.jpg<br/> * @param variableParmeterLength ; int, third parameter length.<br/> * @param drawString variableParmeterLength ;String [] .<br/> */ public void graphicsGeneration(String imgurl,String imageOutPathName,int variableParmeterLength,String...drawString) { //The width of the picture int imageWidth = 500; //The height of the picture int imageHeight = 400; image = new BufferedImage(imageWidth, imageHeight, BufferedImage.TYPE_INT_RGB); Graphics graphics = image.getGraphics(); graphics.setColor(Color.WHITE); //drawing image graphics.fillRect(0, 0, imageWidth, imageHeight); graphics.setColor(Color.BLACK); //draw string string , left margin,top margin for(int i = 0,j = variableParmeterLength;i < j;i++){ graphics.drawString(drawString[i], 50, 10+15*i); } //draw image url ImageIcon imageIcon = new ImageIcon(imgurl); //draw image , left margin,top margin //The coordinates of the top left corner as the center(x,y)[left top angle] //Image observer :If img is null, this method does not perform any action graphics.drawImage(imageIcon.getImage(), 200, 0, null); createImage(imageOutPathName); } public BufferedImage getImage() { return image; } public void setImage(BufferedImage image) { this.image = image; } }
服务器,启动的时候,调用一次,生成默认图片到服务器“/servertempdictory/fileicon/”目录下:
//create default verification code String fileIconDictory = serverPath+\"\\\\servertempdictory\\\\fileicon\"; imageTool.creatDefaultVerificationCode(fileIconDictory);
生成动态验证码,并保存值到session中(此处有登录和注册的分路,这个读者可忽略,走一条既可):
/** * creat verification code * */ public void verificationcode(){ //response HttpServletResponse response = ServletActionContext.getResponse(); //request HttpServletRequest request = ServletActionContext.getRequest(); //verification code demander String vCdemander = request.getParameter(\"vcdemander\"); try{ //set encoding request.setCharacterEncoding(\"utf-8\"); response.setContentType(\"text/html;charset=utf-8\"); //Verification code tool VerificationCodeTool vcTool = new VerificationCodeTool(); BufferedImage image = vcTool.drawVerificationCodeImage(); //Verification code result int vcResult = vcTool.getXyresult(); String vcValue = vcTool.getRandomString(); //Set ban cache //Cache-control : Specify the request and response following caching mechanism //no-cache: Indicates a request or response message cannot cache response.setHeader(\"Cache-Control\", \"no-cache\"); //Entity header field response expiration date and time are given response.setHeader(\"Pragma\", \"No-cache\"); response.setDateHeader(\"Expires\", 0); // Set the output stream content format as image format response.setContentType(\"image/jpeg\"); //session //true: if the session exists, it returns the session, or create a new session. //false: if the session exists, it returns the session, otherwise it returns null. HttpSession session=request.getSession(true); //set verificationcode to session //login if(\"userlogin\".equals(vCdemander)){ session.setAttribute(\"verificationcodeuserlogin\",vcResult); } //regiser if(\"userregister\".equals(vCdemander)){ session.setAttribute(\"verificationcodeuserregister\",vcResult); } //To the output stream output image ImageIO.write(image, \"JPEG\", response.getOutputStream()); LOG.info(\"获取验证码成功 :\\n验证码:\"+vcValue+\"\\n验证码结果:\"+vcResult); } catch (Exception e) { LOG.error(\"获取验证码失败\",e); } }
用struts2实现,所以配置文件struts.xml:
<!-- Set whether to support dynamic method calls, true to support, false does not support. --> <constant name=\"struts.enable.DynamicMethodInvocation\" value=\"true\" /> <!-- The suffix specified request --> <constant name=\"struts.action.extension\" value=\"do,go,tsXs,action\"></constant> <!-- user operation [first login server,server initialize]--> <package name=\"user\" namespace=\"/fileshare\" extends=\"struts-default\"> <!-- user operate ; The wildcard method call--> <action name=\"user*\" class=\"com.tsXs.fileshare.controller.UserController\" method=\"{1}\"> <result name=\"success\">/view/common/message.jsp</result> <result name=\"error\">/view/userLogin.jsp</result> </action> </package>
页面jsp显示代码:
<tr> <td width=\"100\"> <span class=\"hint\">*[验证码]:只能输入数字和负号\"-\"</span> </td> </tr> <tr> <td width=\"100\"> <label for=\"userRegPassWord\">验证码</label> <input type=\"text\" id=\"verificationcodereg\" name=\"verificationcodereg\" tabindex=\"3\" maxlength=\"3\" class=\"t_input\" value=\"\" style=\"ime-mode:disabled;\" οnblur=\"checkuserverificationcode(this);\" οnkeypress=\"return (/[\\d-]/.test(String.fromCharCode(event.keyCode)));\" /> <span id=\"usvcmsg\"></span> <input type=\"hidden\" id=\"verificationcoderegflag\" value=\"\" /> </td> </tr> <tr> <td width=\"140\"> <div id=\"refreshvc\"> <span οnclick=\"refreshvc();\" style=\"padding-left: 49px;cursor: pointer;\"><img id=\"verificationcodeimg\" src=\"${pageContext.request.contextPath}/servertempdictory/fileicon/defaultverificationcode.jpeg\" /> <span style=\"height: 30px;width: 16px;padding-left: 4px;\"><img src=\"image/refreshvc.png\" /></span> <span style=\"font-size: 12px;color:#2c629e; width: 20px;\">换一张</span> </span> </div> </td> </tr>
在js中用正则,保证只能输入,最多3位,可以在数字前输入一个\”-\”,即onkeypress保证只能输入数字和\”-\”:
var userverificationcoderegex = /^(-{0,1}\\d+){1,3}$/; if(userverificationcoderegex.test(userverificationcode)){.....
jsp图片效果:
js动态刷新验证码:
$(document).ready(function(){ //load verificatino code refreshvc(); }); //refresh verification code function refreshvc(){ var path = $(\"#contextPath\").val(); var refreshvcurl =path+\"/fileshare/userverificationcode.tsXs?vcdemander=userregister&time=\"+new Date(); $(\"#verificationcodeimg\").attr(\"src\",refreshvcurl); }
验证码验证:
/** * checkverificationcode : check verification code equals */ public void checkverificationcode(){ //request HttpServletRequest request = ServletActionContext.getRequest(); //response HttpServletResponse response = ServletActionContext.getResponse(); //output stream PrintWriter out = null; //session HttpSession session = request.getSession(); //verification code from client String vcclient = null; //verification code from server String vcserver = null; //verification code demander String vCdemander = request.getParameter(\"vcdemander\"); //check verification code to clien flag String checktoclienflag = null; try{ //get verificationcode to session //login if(\"userlogin\".equals(vCdemander)){ vcclient = request.getParameter(\"vclogincode\"); vcserver = String.valueOf(session.getAttribute(\"verificationcodeuserlogin\")); } //regiser if(\"userregister\".equals(vCdemander)){ vcclient = request.getParameter(\"vcregcode\"); vcserver = String.valueOf(session.getAttribute(\"verificationcodeuserregister\")); } vcclient = UserController.encodingconvert(vcclient); vcclient = vcclient == null ? \"\" : vcclient; if(vcclient.equals(vcserver)){ checktoclienflag = \"vcok\"; }else{ checktoclienflag = \"vcwrong\"; } //set no cache,content type ,encoding response.setHeader(\"Cache-Control\", \"no-cache\"); response.setContentType(\"text/html\"); response.setCharacterEncoding(\"GBK\"); //output stream out = response.getWriter(); out.print(checktoclienflag); LOG.info(\"验证码:vcclient: \"+vcclient+\"vcserver: \"+vcserver+\"验证顺利\"); }catch (Exception e) { LOG.error(\"vcclient: \"+vcclient+\"vcserver: \"+vcserver+\"验证失败\",e); }finally{ out.flush(); out.close(); } }
properties辅助类:
/** * Copyright (c) 2015,TravelSky. * All Rights Reserved. * TravelSky CONFIDENTIAL * * Project Name:filesharetss * Package Name:com.tss.fileshare.controller.tools * File Name:PropertiesFileOperation.java * Date:2015-2-27 下午05:30:05 * */ package com.tsXs.fileshare.tools; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.Enumeration; import java.util.Properties; import org.apache.log4j.Logger; /** * * ClassName: PropertiesFileOperationTool <br/> * Description: inner class Properties file operation <br/> * Date: 2015-2-27 下午05:10:52 <br/> * <br/> * * @author yptian@aliyun.com * * first made * @version 1.0.0<br/> * */ public class PropertiesTool { // LOG private static final Logger LOG = Logger.getLogger(PropertiesTool.class); // Singleton instance private static PropertiesTool instance = new PropertiesTool(); private static Properties properties; /** * * Creates a new Singleton instance of PropertiesFileOperation.<br/> */ private PropertiesTool() { } /** * getInstance :get properties object * @param propertiesFilePathName properties file path and name * @return */ public static PropertiesTool getInstance(String propertiesFilePathName){ properties = loadPropertiesFile(propertiesFilePathName); return instance; } /** * * loadPropertiesFile:Load properties file by path and name<br/> * @param propertiesFilePathName path and name of properties file <br/> * @return properties properties */ private static Properties loadPropertiesFile(String propertiesFilePathName) { Properties properties = new Properties(); InputStream isLoad = PropertiesTool.class.getClassLoader().getResourceAsStream(propertiesFilePathName); try { // loader properties properties.load(isLoad); } catch (IOException e) { LOG.error(propertiesFilePathName + \" properties file read failure\", e); } finally { try { isLoad.close(); } catch (IOException e) { LOG.error(\"properties file stream close error\",e); } } return properties; } /** * * * getPropertiesValue:Get properties value by key <br/> * @param key properties key <br/> * @return value properties value */ public String getPropertiesValue(String key) { return properties.getProperty(key); } public static String getInstanceByServerRealPathOfValue(String propertiesFileServerRealPathName,String key){ String pValue = null; try { InputStream isrLoad = new FileInputStream(propertiesFileServerRealPathName); properties.load(isrLoad); isrLoad.close(); pValue = properties.getProperty(key); } catch (IOException e) { LOG.error(\"Failed to get the value under the server of the properties file\",e); } return pValue; } /** * * getProperties:Get properties by key and value <br/> * @param key properties key <br/> * @param value properties value */ public void setProperties(String filePath,String key,String value){ try { InputStream is = new FileInputStream(filePath); OutputStream os = new FileOutputStream(filePath); properties.load(is); properties.setProperty(key, value); properties.store(os, null); os.flush(); is.close(); os.close(); } catch (IOException e) { LOG.error(\"properties file stream close error\",e); } } /** * * alterProperties:alter properties by key and value <br/> * @param key properties key <br/> * @param value properties value */ public void alterProperties(String filePath,String key,String value){ try{ InputStream is = new FileInputStream(filePath); OutputStream os = new FileOutputStream(filePath); properties.load(is); properties.remove(key); properties.setProperty(key, value); properties.store(os, null); os.flush(); is.close(); os.close(); } catch (IOException e) { LOG.error(\"properties file stream close error\",e); } } /** * * getAllProperties:Read the properties of all the information <br/> * @return properties information */ @SuppressWarnings(\"rawtypes\") public String getAllProperties(){ Enumeration en = properties.propertyNames(); StringBuffer sf = new StringBuffer(); while (en.hasMoreElements()) { String key = (String) en.nextElement(); String value = properties.getProperty (key); sf.append(\"\\n\"+key); sf.append(\"=\"); value = value.replace(\":\", \"\\\\:\"); sf.append(value); } return sf.toString(); } }
到此这篇关于Java实现中文算数验证码的实现示例(算数运算+-*/)的文章就介绍到这了,更多相关Java 中文算数验证码内容请搜索自学编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持自学编程网!