本文实例为大家分享了Java动态验证码生成的具体代码,供大家参考,具体内容如下
说明: 今天给大家来带来一个自动生成验证码的处理方法。验证码的出现有效减少了注入灌水以及破解密码等恶意操作,提高了系统运行的流畅性,保护了系统用户的隐私安全,具体实现方法如下:
1.首先我们先编写一个专门的验证码生成工具类,该工具类代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 |
package com.ordering.util;
import java.awt.Color; import java.awt.Font; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.image.BufferedImage; import java.util.Random;
/** * 验证码生成器 * @author 诺坎普10号 * @date 2020-2-25 */ public class CpachaUtil {
/** * 验证码来源 */ final private char [] code = { '2' , '3' , '4' , '5' , '6' , '7' , '8' , '9' , 'a' , 'b' , 'c' , 'd' , 'e' , 'f' , 'g' , 'h' , 'i' , 'j' , 'k' , 'm' , 'n' , 'p' , 'q' , 'r' , 's' , 't' , 'u' , 'v' , 'w' , 'x' , 'y' , 'z' , 'A' , 'B' , 'C' , 'D' , 'E' , 'F' , 'G' , 'H' , 'J' , 'K' , 'L' , 'M' , 'N' , 'P' , 'Q' , 'R' , 'S' , 'T' , 'U' , 'V' , 'W' , 'X' , 'Y' , 'Z' }; /** * 字体 */ final private String[] fontNames = new String[]{ "黑体" , "宋体" , "Courier" , "Arial" , "Verdana" , "Times" , "Tahoma" , "Georgia" }; /** * 字体样式 */ final private int [] fontStyles = new int []{ Font.BOLD, Font.ITALIC|Font.BOLD };
/** * 验证码长度 * 默认4个字符 */ private int vcodeLen = 4 ; /** * 验证码图片字体大小 * 默认17 */ private int fontsize = 21 ; /** * 验证码图片宽度 */ private int width = (fontsize+ 1 )*vcodeLen+ 10 ; /** * 验证码图片高度 */ private int height = fontsize+ 12 ; /** * 干扰线条数 * 默认3条 */ private int disturbline = 3 ;
public CpachaUtil(){}
/** * 指定验证码长度 * @param vcodeLen 验证码长度 */ public CpachaUtil( int vcodeLen) { this .vcodeLen = vcodeLen; this .width = (fontsize+ 1 )*vcodeLen+ 10 ; }
/** * 指定验证码长度、图片宽度、高度 * @param vcodeLen * @param width * @param height */ public CpachaUtil( int vcodeLen, int width, int height) { this .vcodeLen = vcodeLen; this .width = width; this .height = height; }
/** * 生成验证码图片 * @param vcode 要画的验证码 * @param drawline 是否画干扰线 * @return */ public BufferedImage generatorVCodeImage(String vcode, boolean drawline){ //创建验证码图片 BufferedImage vcodeImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); Graphics g = vcodeImage.getGraphics(); //填充背景色 g.setColor( new Color( 246 , 240 , 250 )); g.fillRect( 0 , 0 , width, height); if (drawline){ drawDisturbLine(g); } //用于生成伪随机数 Random ran = new Random(); //在图片上画验证码 for ( int i = 0 ;i < vcode.length();i++){ //设置字体 g.setFont( new Font(fontNames[ran.nextInt(fontNames.length)], fontStyles[ran.nextInt(fontStyles.length)], fontsize)); //随机生成颜色 g.setColor(getRandomColor()); //画验证码 g.drawString(vcode.charAt(i)+ "" , i*fontsize+ 10 , fontsize+ 5 ); } //释放此图形的上下文以及它使用的所有系统资源 g.dispose();
return vcodeImage; } /** * 获得旋转字体的验证码图片 * @param vcode * @param drawline 是否画干扰线 * @return */ public BufferedImage generatorRotateVCodeImage(String vcode, boolean drawline){ //创建验证码图片 BufferedImage rotateVcodeImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); Graphics2D g2d = rotateVcodeImage.createGraphics(); //填充背景色 g2d.setColor( new Color( 246 , 240 , 250 )); g2d.fillRect( 0 , 0 , width, height); if (drawline){ drawDisturbLine(g2d); } //在图片上画验证码 for ( int i = 0 ;i < vcode.length();i++){ BufferedImage rotateImage = getRotateImage(vcode.charAt(i)); g2d.drawImage(rotateImage, null , ( int ) ( this .height * 0.7 ) * i, 0 ); } g2d.dispose(); return rotateVcodeImage; } /** * 生成验证码 * @return 验证码 */ public String generatorVCode(){ int len = code.length; Random ran = new Random(); StringBuffer sb = new StringBuffer(); for ( int i = 0 ;i < vcodeLen;i++){ int index = ran.nextInt(len); sb.append(code[index]); } return sb.toString(); } /** * 为验证码图片画一些干扰线 * @param g */ private void drawDisturbLine(Graphics g){ Random ran = new Random(); for ( int i = 0 ;i < disturbline;i++){ int x1 = ran.nextInt(width); int y1 = ran.nextInt(height); int x2 = ran.nextInt(width); int y2 = ran.nextInt(height); g.setColor(getRandomColor()); //画干扰线 g.drawLine(x1, y1, x2, y2); } } /** * 获取一张旋转的图片 * @param c 要画的字符 * @return */ private BufferedImage getRotateImage( char c){ BufferedImage rotateImage = new BufferedImage(height, height, BufferedImage.TYPE_INT_ARGB); Graphics2D g2d = rotateImage.createGraphics(); //设置透明度为0 g2d.setColor( new Color( 255 , 255 , 255 , 0 )); g2d.fillRect( 0 , 0 , height, height); Random ran = new Random(); g2d.setFont( new Font(fontNames[ran.nextInt(fontNames.length)], fontStyles[ran.nextInt(fontStyles.length)], fontsize)); g2d.setColor(getRandomColor()); double theta = getTheta(); //旋转图片 g2d.rotate(theta, height/ 2 , height/ 2 ); g2d.drawString(Character.toString(c), (height-fontsize)/ 2 , fontsize+ 5 ); g2d.dispose();
return rotateImage; } /** * @return 返回一个随机颜色 */ private Color getRandomColor(){ Random ran = new Random(); return new Color(ran.nextInt( 220 ), ran.nextInt( 220 ), ran.nextInt( 220 )); } /** * @return 角度 */ private double getTheta(){ return (( int ) (Math.random()* 1000 ) % 2 == 0 ? - 1 : 1 )*Math.random(); }
/** * @return 验证码字符个数 */ public int getVcodeLen() { return vcodeLen; } /** * 设置验证码字符个数 * @param vcodeLen */ public void setVcodeLen( int vcodeLen) { this .width = (fontsize+ 3 )*vcodeLen+ 10 ; this .vcodeLen = vcodeLen; } /** * @return 字体大小 */ public int getFontsize() { return fontsize; } /** * 设置字体大小 * @param fontsize */ public void setFontsize( int fontsize) { this .width = (fontsize+ 3 )*vcodeLen+ 10 ; this .height = fontsize+ 15 ; this .fontsize = fontsize; } /** * @return 图片宽度 */ public int getWidth() { return width; } /** * 设置图片宽度 * @param width */ public void setWidth( int width) { this .width = width; } /** * @return 图片高度 */ public int getHeight() { return height; } /** * 设置图片高度 * @param height */ public void setHeight( int height) { this .height = height; } /** * @return 干扰线条数 */ public int getDisturbline() { return disturbline; } /** * 设置干扰线条数 * @param disturbline */ public void setDisturbline( int disturbline) { this .disturbline = disturbline; }
} |
2.然后在页面端定义一个显示验证码的控件,再写一个js函数来对后台动态生成验证码方法进行调用 ,主要代码如下:
1 2 3 4 5 6 7 8 9 |
< div class = "login-center-input-text" >验证码</ div > < img id = "cpacha-img" title = "点击切换验证码" style = "cursor:pointer;" src = "get_cpacha?vl=4&w=150&h=40&type=loginCpacha" width = "110px" height = "30px" onclick = "changeCpacha()" > </ div >
< script type = "text/javascript" > function changeCpacha(){ $("#cpacha-img").attr("src",'get_cpacha?vl=4&w=150&h=40&type=loginCpacha&t=' + new Date().getTime()); } </ script > |
3.控制器中代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
/** * 本系统所有的验证码均采用此方法 * * @param vcodeLen * @param width * @param height * @param cpachaType:用来区别验证码的类型,传入字符串 * @param request * @param response */ @RequestMapping (value = "/get_cpacha" , method = RequestMethod.GET) public void generateCpacha( @RequestParam (name = "vl" , required = false , defaultValue = "4" ) Integer vcodeLen, @RequestParam (name = "w" , required = false , defaultValue = "100" ) Integer width, @RequestParam (name = "h" , required = false , defaultValue = "30" ) Integer height, @RequestParam (name = "type" , required = true , defaultValue = "loginCpacha" ) String cpachaType, HttpServletRequest request, HttpServletResponse response) { //根据页面传入的验证码长度、图片宽度以及图片长度来实例化验证码实体 CpachaUtil cpachaUtil = new CpachaUtil(vcodeLen, width, height); //生成验证码 String generatorVCode = cpachaUtil.generatorVCode(); //把验证码存入session request.getSession().setAttribute(cpachaType, generatorVCode); //根据验证码生成相应的验证码图片 BufferedImage generatorRotateVCodeImage = cpachaUtil.generatorRotateVCodeImage(generatorVCode, true ); try { ImageIO.write(generatorRotateVCodeImage, "gif" , response.getOutputStream()); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } |
4.实现效果 如下图所示:
5.控制器验证码验证部分 如下图所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
//若验证码为空 if (StringUtils.isEmpty(cpacha)) { ret.put( "type" , "error" ); ret.put( "msg" , "请填写验证码!" ); return ret; } //获取保存在session中的登录验证码对象 Object loginCpacha = request.getSession().getAttribute( "loginCpacha" ); //若登录验证码实体对象为空 if (loginCpacha == null ) { ret.put( "type" , "error" ); ret.put( "msg" , "会话超时,请刷新页面!" ); return ret; } //若输入的验证码转化成大写之后不等于转换成大写的session中保存的验证码 if (!cpacha.toUpperCase().equals(loginCpacha.toString().toUpperCase())) { ret.put( "type" , "error" ); ret.put( "msg" , "验证码错误!" ); //实例化日志信息实体 OrderingLog orderingLog = new OrderingLog( "用户名为" + user.getOuUsername() + "的用户登录时输入验证码错误!" , new Date()); //添加日志信息 logService.addLog(orderingLog); return ret; } |
注意:
只有当你把当前系统时间传入该验证码生成工具类中,才能实现点击验证码图片,实时自动替换验证码,如下图所示:
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
原文链接:https://blog.csdn.net/weixin_44009447/article/details/105667939