图片验证码——base64编码的使用
一、介绍:
1.base64编码简介:
Base64就是一种编码格式。Base64要求把每三个8Bit的字节转换为四个6Bit的字节(3*8 = 4*6 = 24),然后把6Bit再添两位高位0,组成四个8Bit的字节,也就是说,转换后的字符串理论上将要比原来的长1/3。
2.使用base64编码的优点:
①减少了网络请求:采用http形式的url的话都会额外发送一次请求,网页发送的http请求次数越多,会造成页面加载速度越慢。
②不会造成跨域请求的问题:因为采用Base64编码的图片是随着页面一起加载的。
③不会造成清理图片缓存问题。
3.使用base64编码的缺点:
①数据传输量变大,代码的可读性不高。
②对于IE 8以下的浏览器不可使用,IE 8以上的浏览器可以使用,但对大小做出了限制。
所以此方法适合于图片像素小的。
二、使用例子:
1.html
<!--图片验证码--> <div> <div> <input type="text" id="codeImg" placeholder="请输入验证码" maxlength="4"> </div> <div> <a href="javascript:void(0);" title="点击更换验证码"> <img id="imgVerify" src="" alt="更换验证码" onclick="getVerify(this);"> </a> </div> </div> <script type="text/javascript"> var imgVerify = $("#imgVerify").get(0); $(function () { getVerify(imgVerify); }); // 图片验证码 function getVerify(obj) { $.ajax({ type: "GET", url: httpRequestUrl + "/getVerifyPic", success: function (result) { obj.src = "data:image/jpeg;base64," + result; } }); } </script>
2.接口
//controller层 @Autowired private YZMService yzmService; @RequestMapping(value = "/getVerifyPic", method = RequestMethod.GET) public String getVerifyPic(HttpServletRequest request) { final String RANDOMCODEKEY= "RANDOMVALIDATECODEKEY";//放到session中的key Map<String,String> map = new HashMap<String,String>(); map = yzmService.getVerifyPic(); yzmService.getVerifyPic(); request.getSession().setAttribute(RANDOMCODEKEY, map.get("num")); return map.get("pic"); } //service层 public Map<String,String> getVerifyPic() { RandomValidateCodeUtil randomValidateCode = new RandomValidateCodeUtil(); return randomValidateCode.getRandcode();//输出验证码图片方法 }
3.验证码工具类
public class RandomValidateCodeUtil { public static final String RANDOMCODEKEY= "RANDOMVALIDATECODEKEY";//放到session中的key // private String randString = "0123456789";//随机产生只有数字的字符串 private String // private String randString = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";//随机产生只有字母的字符串 private String randString = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";//随机产生数字与字母组合的字符串 private int width = 95;// 图片宽 private int height = 25;// 图片高 private int lineSize = 40;// 干扰线数量 private int stringNum = 4;// 随机产生字符数量 private static final Logger logger = LoggerFactory.getLogger(RandomValidateCodeUtil.class); private Random random = new Random(); /** * 获得字体 */ private Font getFont() { return new Font("Fixedsys", Font.CENTER_BASELINE, 18); } /** * 获得颜色 */ private Color getRandColor(int fc, int bc) { if (fc > 255) fc = 255; if (bc > 255) bc = 255; 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); } /** * 生成随机图片 */ public Map<String,String> getRandcode() { // HttpSession session = request.getSession(); // BufferedImage类是具有缓冲区的Image类,Image类是用于描述图像信息的类 BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_BGR); Graphics g = image.getGraphics();// 产生Image对象的Graphics对象,改对象可以在图像上进行各种绘制操作 g.fillRect(0, 0, width, height);//图片大小 g.setFont(new Font("Times New Roman", Font.ROMAN_BASELINE, 18));//字体大小 g.setColor(getRandColor(110, 133));//字体颜色 // 绘制干扰线 for (int i = 0; i <= lineSize; i++) { drowLine(g); } // 绘制随机字符 String randomString = ""; for (int i = 1; i <= stringNum; i++) { randomString = drowString(g, randomString, i); } logger.info(randomString); //将生成的随机字符串保存到session中 // session.removeAttribute(RANDOMCODEKEY); // session.setAttribute(RANDOMCODEKEY, randomString); g.dispose(); String base64 = null; try { // 将内存中的图片通过流动形式输出到客户端 ByteArrayOutputStream baos = new ByteArrayOutputStream(); ImageIO.write(image, "JPEG", baos);//图片格式 byte[] bytes = baos.toByteArray(); base64 = new BASE64Encoder().encodeBuffer(bytes).trim(); } catch (Exception e) { logger.error("将内存中的图片通过流动形式输出到客户端失败>>>> ", e); } Map<String,String> map = new HashMap<String,String>(); map.put("num", randomString); map.put("pic", base64); return map; } /** * 绘制字符串 */ private String drowString(Graphics g, String randomString, int i) { g.setFont(getFont()); g.setColor(new Color(random.nextInt(101), random.nextInt(111), random .nextInt(121))); String rand = String.valueOf(getRandomString(random.nextInt(randString .length()))); randomString += rand; g.translate(random.nextInt(3), random.nextInt(3)); g.drawString(rand, 13 * i, 16); return randomString; } /** * 绘制干扰线 */ private void drowLine(Graphics g) { int x = random.nextInt(width); int y = random.nextInt(height); int xl = random.nextInt(13); int yl = random.nextInt(15); g.drawLine(x, y, x + xl, y + yl); } /** * 获取随机的字符 */ public String getRandomString(int num) { return String.valueOf(randString.charAt(num)); } }