首页

在分布式系统基于Redis通过将图形验证码以Base64.encodeBase64String加密后的在img标签正常显示的完整代码示例说明

标签:图形验证码,自定义,代码示例,ImageIO,Base64,redis,分布式,session,会话     发布时间:2017-06-22   

一、前言

原来对于单应用将生成的图形验证码存在Session会话中,但是在分布式环境在,当请求切换的cluster的备机,备机上没有UUID关联的验证码数据。因此,在分布式环境中,需要将UUID的验证码存储在Redis中,提交的时候统一根据UUID从内存中加载并验证,另外生成的图形验证码通过Base64.encodeBase64String转码后和UUID一起以JSON数据格式返回前端,这样生成的base64的验证码的数据可以直接贴在img标签的src属性中渲染显示。

二、代码示例

1.VerificationCodeController中通过接口2个接口分别获取返回图形的UUID及图形的Base64加密码接口、通过Img标签的src属性赋值图形加密串渲染出图形

import java.awt.Color;@b@import java.awt.Font;@b@import java.awt.Graphics;@b@import java.awt.image.BufferedImage;@b@import java.io.ByteArrayOutputStream;@b@import java.io.IOException;@b@import java.io.PrintWriter;@b@import java.util.Random;@b@import java.util.UUID;@b@@b@import javax.imageio.ImageIO;@b@import javax.servlet.ServletException;@b@import javax.servlet.http.HttpServletRequest;@b@import javax.servlet.http.HttpServletResponse;@b@@b@import org.apache.commons.codec.binary.Base64;@b@import org.springframework.stereotype.Controller;@b@import org.springframework.ui.ModelMap;@b@import org.springframework.web.bind.annotation.RequestMapping;@b@import org.springframework.web.bind.annotation.RequestMethod;@b@import org.springframework.web.bind.annotation.ResponseBody;@b@@b@@b@/**@b@ * @描述:一次性校验码@b@ * @author@b@ */@b@@Controller@b@public class VerificationCodeController{@b@	@b@	// 渲染随机背景颜色@b@	private Color getRandColor(int fc,int bc){@b@		Random random = new Random();@b@		if(fc>255) fc=255;@b@		if(bc>255) bc=255;@b@		int r=fc+random.nextInt(bc-fc);@b@		int g=fc+random.nextInt(bc-fc);@b@		int b=fc+random.nextInt(bc-fc);@b@		return new Color(r,g,b);@b@	}@b@	@b@	 //渲染固定背景颜色@b@	private Color getBgColor(){@b@	   return new Color(200,200,200);@b@	}@b@	@b@	@b@	private BufferedImage  drawImg(){@b@		return drawImg(false);@b@	}@b@	@b@	/**@b@	 * 画验证码图形@b@	 * @param isDrawLine@b@	 * @return@b@	 */@b@	private BufferedImage  drawImg(boolean isDrawLine){@b@		// 在内存中创建图象@b@		int width=120, height=20;@b@		BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);@b@		// 获取图形上下文@b@		Graphics g = image.getGraphics();@b@		Random random = new Random();@b@		// 设定背景色@b@		g.setColor(getBgColor());@b@		g.fillRect(0, 0, width, height);@b@		// 设定字体@b@		g.setFont(new Font("Times New Roman",Font.PLAIN,18));@b@		// 画边框@b@		//g.setColor(new Color());@b@		//g.drawRect(0,0,width-1,height-1);@b@@b@		/**随机产生155条干扰线,使图象中的认证码不易被其它程序探测到*/@b@		@b@		if(isDrawLine){@b@			g.setColor(getRandColor(160,200));@b@			for (int i=0;i<155;i++){@b@				int x = random.nextInt(width);@b@				int y = random.nextInt(height);@b@				int xl = random.nextInt(12);@b@				int yl = random.nextInt(12);@b@				g.drawLine(x,y,x+xl,y+yl);@b@			}@b@		}@b@		@b@		// 取随机产生的认证码(8位数字和字母混合)@b@		String sRand="";@b@		String verCode="";@b@		char[] seds = new char[]{'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','0','1','2','3','4','5','6','7','8','9'};@b@		for (int i=0;i<8;i++){@b@			int index = random.nextInt(seds.length);@b@			char cc = seds[index];@b@			if((i+1)%2==0){@b@				verCode+=cc;@b@				g.setColor(new Color(255,0,0));@b@			}else{@b@				g.setColor(new Color(0,0,0));@b@			}@b@			sRand+=cc;@b@			// 将认证码随机打印不同的颜色显示出来@b@			//g.setColor(new Color(20+random.nextInt(110),20+random.nextInt(110),20+random.nextInt(110)));// 调用函数出来的颜色相同,可能是因为种子太接近,所以只能直接生成@b@			g.drawString(cc+"",13*i+6,16);@b@		}@b@		// 图象生效@b@		g.dispose();@b@		@b@		return image;@b@	}@b@	@b@	private String encodeBase64ImgCode()throws ServletException, IOException {@b@		BufferedImage codeImg=drawImg();@b@		/*// 将认证码存入SESSION@b@		request.getSession().setAttribute("rand",sRand);*/@b@		// 将认证码存入redis@b@		// RedisUtil.saveValue(redis, uuid.getBytes(),verCode.getBytes(), 60 * 5 * 1);@b@		ByteArrayOutputStream out = new ByteArrayOutputStream();@b@		boolean flag = ImageIO.write(codeImg, "JPEG", out);@b@		byte[] b = out.toByteArray();@b@		String imgString = Base64.encodeBase64String(b);@b@		return "data:image/JPEG;base64," + imgString;@b@	}@b@	@b@	 @b@	/**@b@	 * @描述:生成校验码@b@	 * @return@b@	 * @param form@b@	 * @throws IOException @b@	 */@b@	@RequestMapping(value="/generateCode.do",method={RequestMethod.POST,RequestMethod.GET})@b@	public @ResponseBody ModelMap generateCode(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {@b@		ModelMap model = new ModelMap();@b@		@b@		//生成验证码uuid@b@		model.put("id", UUID.randomUUID().toString());@b@		@b@		// 设置页面不缓存@b@		response.setHeader("Pragma","No-cache");@b@		response.setHeader("Cache-Control","no-cache");@b@		response.setDateHeader("Expires", 0);@b@		@b@		model.put("img",encodeBase64ImgCode());//获取通过base64加密后图形码字符串@b@		return model;@b@	}@b@	 @b@	@b@	 @RequestMapping("/hello")@b@	 public @ResponseBody String test() {@b@	    return "hello, world! This com from spring!";@b@	 }@b@	 @b@	 @RequestMapping(value="/springmvc/getOutImgCode")@b@	 public void getOutImgCode(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {@b@		 PrintWriter out = response.getWriter();@b@		 response.setContentType("text/html;charset=utf-8"); @b@		 out.println("<img src=\""+encodeBase64ImgCode()+"\">");@b@		 out.close();@b@	 }@b@	 @b@ @b@	@b@}

2.通过/generateCode.do接口返回JSON的UUID和图形码的加密串,如下图

在分布式系统基于Redis通过将图形验证码以Base64.encodeBase64String加密后的在img标签正常显示的完整代码示例说明

{@b@  "id" : "ebf73be9-52c4-45b3-ab2f-c7e80a1ad815",@b@  "img" : "data:image/JPEG;base64,/9j/4AAQSkZJRgABAgAAAQABAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQND ....... 6ipqUUAFFFFABRRRQAUUUUAFFFFAH/2Q=="@b@}

通过img标签将就可以将base64的加密字符串渲染为图形码图片,如下图所示

在分布式系统基于Redis通过将图形验证码以Base64.encodeBase64String加密后的在img标签正常显示的完整代码示例说明