验证码

来源:互联网 发布:知道arp攻击源mac地址 编辑:程序博客网 时间:2024/05/29 18:29

1.随机验证码生产

public class RandomCodeUtil {private ByteArrayInputStream byteImg;// byte图像1private BufferedImage buffImg;// buff图像2private String str;// 验证码private int codeCount = 4;// 定义图片上显示验证码的个数  private int xx = 28; // 验证码水平位置偏移private int codeY = 30; // 验证码垂直位置偏移    private int fontHeight = 30; // 字体大小    private int runLin = 60;// 干扰线数private int red = 255, green = 100, blue = 50; // 字体数值范围内的随机颜色private int bgfc = 150, bgbc = 200;// 背景颜色private int linfc = 200, linbc = 250;// 干扰线颜色private int width = 158, height =40;// 图像的宽,高    //不包含字母 i l o I,数字 0 1char[] codeSequence = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', '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', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '2', '3', '4', '5', '6', '7', '8', '9', }; private int ruNumber = codeSequence.length-1; //0~ruNumber之间的随着自然数 获得验证码private RandomCodeUtil() {init();// 初始化属性}/** * 取得RandomNumUtil实例 */public static RandomCodeUtil Instance() {return new RandomCodeUtil();}/** * 取得验证码图片byteImg */public ByteArrayInputStream GetByteImg() {return this.byteImg;}/** * 取得验证码图片buffImg */public BufferedImage getBuffImg() {return this.buffImg;}/** * 取得图片的验证码字符串 */public String getString() {return this.str;}/** * 初始化属性 */private void init() {// 在内存中创建图象BufferedImage buffImg = new BufferedImage(width, height,BufferedImage.TYPE_INT_RGB);// 获取图形上下文Graphics g = buffImg.getGraphics();// 生成随机类Random random = new Random();// 设定背景色g.setColor(getRandColor(bgfc, bgbc));g.fillRect(0, 0, width, height);// 设定字体g.setFont(new Font("Times New Roman", Font.BOLD, fontHeight));// 随机产生runLin条干扰线,使图象中的认证码不易被其它程序探测到g.setColor(getRandColor(linfc, linbc));for (int i = 0; i < runLin ; i++) {int x = random.nextInt(width);int y = random.nextInt(height);int xl = random.nextInt(12);int yl = random.nextInt(12);g.drawLine(x, y, x + xl, y + yl);}// randomCode用于保存随机产生的验证码,以便用户登录后进行验证。      StringBuffer randomCode = new StringBuffer(); //随机产生codeCount数字的验证码for (int i = 0; i < codeCount; i++) {// 得到随机产生的验证码数字。  String code = String.valueOf(codeSequence[random.nextInt(ruNumber)]); //0~ruNumber之间的随着自然数// 产生随机的颜色分量来构造颜色值,这样输出的每位数字的颜色值都将不同。             // 用随机产生的颜色将验证码绘制到图像中。              g.setColor(new Color(random.nextInt(red), random.nextInt(green), random.nextInt(blue)));             // 调用函数出来的颜色相同,可能是因为种子太接近,所以只能直接生成            g.drawString(code, (i + 1) * xx, codeY);     // 将产生的四个随机数组合在一起。              randomCode.append(code); }// 赋值验证码this.str = randomCode.toString();// 图象生效g.dispose();/************赋值byte图像1 输出图片流**************/ByteArrayInputStream input = null;ByteArrayOutputStream output = new ByteArrayOutputStream();try {ImageOutputStream imageOut = ImageIO.createImageOutputStream(output);ImageIO.write(buffImg, "JPEG", imageOut);imageOut.close();input = new ByteArrayInputStream(output.toByteArray());} catch (Exception e) {System.out.println("验证码图片产生出现错误:" + e.toString());}this.byteImg = input;// 赋值byte图像1/************赋值buff图像2 输出图像**************/this.buffImg = buffImg; // 赋值buff图像2}/** * 给定范围获得随机颜色 */private Color getRandColor(int fc, int bc) {Random random = new Random();if (fc > 255)fc = 255;if (bc > 255)bc = 255;int r = fc + random.nextInt(bc - fc);int g = fc + random.nextInt(bc - fc);int b = fc + random.nextInt(bc - fc);return new Color(r, g, b);}}

2.Servlet生成输出到页面

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {RandomCodeUtil rc=RandomCodeUtil.Instance();//禁止reponse中缓存response.setHeader("Pragma", "no-cache");         response.setHeader("Cache-Control", "no-cache");         response.setDateHeader("Expires", 0);         response.setContentType("image/jpeg");                 ServletOutputStream os = response.getOutputStream();   ImageIO.write(rc.getBuffImg(), "jpeg", os);os.close();HttpSession session=request.getSession();   //保存在session中 ,以便于后面 进行验证码 校验 session.setAttribute("img", rc.getString());}


3.切换验证码

注:因为浏览器会缓存验证码图片 ,所以每一次都需要带上不同参数以去缓存 
(自己最初写法)

<script type="text/javascript">//点击更换验证码function refresh(obj) {    obj.src = "${pageContext.servletContext.contextPath}/RandomCode.do?it="+Math.random();}</script>

jsp 页面

<tr><td><input type="text" name="RandomCode"  id="img" placeholder="输入验证码"></td></tr><tr><td><img  src="${pageContext.servletContext.contextPath}/RandomCode.do"   title="点击更换" onclick="refresh(this)" ></td></tr>

优化(老师写法)

<script type="text/javascript">$(function(){changeCode();$("#codeImg").bind("click",changeCode); //id为codeImg的html元素绑定点击事件});function changeCode(){$("#codeImg").attr("src","${pageContext.servletContext.contextPath }/code?"+new Date()); //去缓存}</script>

<div class="form-group"><input type="text" name="code" placeholder="验证码"  class="input input-big"><img alt="验证码" id="codeImg" src=""></div>


4. 验证判断 (用ajax进行判断)

//获取验证码function img(img){var i = $(img).val();var bol = true;// 判断是否为空if (i == null || i == "") {$("#msg").empty();$(img).after("<p id='ms' style='color:#92192d;font-size:14px'>请输入验证码!</p>");return bol = false;}$.ajax({url : "http://localhost:8080/IntegralManager_v1.0/RandIs.do", // 规定发送请求的// URLtype : "post",data : "img=" + i, // 规定要发送到服务器的数据(名)。dataType : "json", // 服务端可能响应的数据类型success : function(date) { // 当请求成功时运行的函数。$("#msg").empty();if (date.msg == "no") { // 不一致$(img).after("<p id='msg' style='color:#92192d;font-size:14px'>验证码错误!</p>");bol = false;}}});return bol;}

servlet 

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//获取随机数HttpSession session=request.getSession();String img=(String)session.getAttribute("img");System.out.println("产生随机数:"+img);String str=request.getParameter("img");System.out.println("输入随机数"+str);PrintWriter pw = response.getWriter();if(img.equalsIgnoreCase(str)){     //不区分大小写 ,以便于用户体验pw.println("{\"msg\":\"yes\"}"); //一致}else{pw.println("{\"msg\":\"no\"}");//不一致}}