逻辑条件不同实现则不同,仿12306的图片验证码

2019-08-17 作者:yzc216.com官网   |   浏览(76)

仿12306的图片验证码,仿12306图片验证码

由于要做一个新项目,所以打算做一个简单的图片验证码。

先说说思路吧:在服务端,从一个文件夹里面找出8张图片,再把8张图片合并成一张大图,在8个小图里面随机生成一个要用户验证的图片分类,如小狗、啤酒等。在前端,访问这个页面时,把图片加载上去,用户在图片上选择提示所需要的图片,当用户点登陆时,根据用户选择的所有坐标判断所选的图片是不是实际上的验证图片。

先放两张效果图:

图片 1图片 2

为了让文件查找比较简单,在图片文件结构上可以这样:

//选取8个图片 public static List<Object> getEightImages() { //保存取到的每一个图片的path,保证图片不会重复 List<String> paths = new ArrayList<String>(); File[] finalImages = new File[8]; List<Object> object = new ArrayList<Object>(); //保存tips String[] tips = new String[8]; for (int i = 0; i < 8; i ) { //获取随机的二级目录 int dirIndex = getRandom(secondaryDirNumbers); File secondaryDir = getFiles()[dirIndex]; //随机到的文件夹名称保存到tips中 tips[i] = secondaryDir.getName(); //获取二级图片目录下的文件 File[] images = secondaryDir.listFiles(); int imageIndex = getRandom(imageRandomIndex); File image = images[imageIndex]; //图片去重 image = dropSameImage(image, paths, tips, i); paths.add(image.getPath()); finalImages[i] = image; } object.add(finalImages); object.add(tips); return object; }

在生成这8张图片中,用一个数组保存所有的文件分类。在这个分类里面可以用随机数选取一个分类做为Key分类,就是用户要选择的所有图片。由于数组是有序的,可以遍历数组中的元素,获取每个key分类图片的位置,方便在用户验证时,进行匹配。

//获取位置,返回的是第几个图片,而不是下标,从1开始,集合第一个元素为tip
 public static List<Object> getLocation(String[] tips) {
  List<Object> locations = new ArrayList<Object>();

  //获取Key分类
  String tip = getTip(tips);
  locations.add(tip);

  int length = tips.length;
  for (int i = 0; i < length; i  ) {
   if (tip.equals(tips[i])) {

    locations.add(i 1);
   }
  }
  return locations;
 }

 

选取了8张图片后,接下来就是合并图片。合并图片可以用到BufferedImage这个类的方法:setRGB()这个方法如果不明白可以看下api文档,上面有详细的说明。

public static void mergeImage(File[] finalImages, HttpServletResponse response) throws IOException {

        //读取图片
        BufferedImage mergeImage = new BufferedImage(800, 400, BufferedImage.TYPE_INT_BGR);

        for (int i = 0; i < 8; i  ) {
            File image = finalImages[i];

            BufferedImage bufferedImage = ImageIO.read(image);
            int width = bufferedImage.getWidth();
            int height = bufferedImage.getHeight();
            //从图片中读取RGB
            int[] imageBytes = new int[width*height];
            imageBytes = bufferedImage.getRGB(0, 0, width, height, imageBytes, 0, width);
            if ( i < 4) {
                mergeImage.setRGB(i*200, 0, width, height, imageBytes, 0, width);
            } else {
                mergeImage.setRGB((i -4 )*200, 200, width, height, imageBytes, 0, width);
            }            

        }


        ImageIO.write(mergeImage, "jpg", response.getOutputStream());
        //ImageIO.write(mergeImage, "jpg", destImage);
    }

 

 

  在controller层中,先把key分类保存到session中,为用户选择图片分类做提示和图片验证做判断。然后把图片流输出到response中,就可以生成验证图片了。

  

        response.setContentType("image/jpeg");  
        response.setHeader("Pragma", "No-cache");  
        response.setHeader("Cache-Control", "no-cache");  
        response.setDateHeader("Expires", 0);

        List<Object> object = ImageSelectedHelper.getEightImages();
        File[] finalImages = (File[]) object.get(0);

        String[] tips = (String[]) object.get(1);
        //所有key的图片位置,即用户必须要选的图片
        List<Object> locations = ImageSelectedHelper.getLocation(tips);

        String tip = locations.get(0).toString();
        System.out.println(tip);
        session.setAttribute("tip", tip);
        locations.remove(0);

        int length = locations.size();
        for (int i = 0; i < length; i  ) {
            System.out.println("实际Key图片位置:"   locations.get(i));
        }

        session.setAttribute("locations", locations);
        ImageMerge.mergeImage(finalImages, response);

 

  在jsp中,为用户的点击生成小图片标记。当用户点图片击时,在父div上添加一个子div标签,并且把他定位为relative, 并且设置zIndex,然后再这个div上添加一个img标签,定位为absolute。在用户的点击时,可以获取点击事件,根据点击事件获取点击坐标,然后减去父div的坐标,就可以获取相对坐标。可以根据自己的喜好定坐标原点,这里的坐标原点是第8个图片的右下角。

  

  <div>
        <div id="base">
            <img src="<%=request.getContextPath()%>/identify">public List<Integer> isPass(String result) {

  String[] xyLocations = result.split(",");
  //保存用户选择的坐标落在哪些图片上
  List<Integer> list = new ArrayList<Integer>();
  //每一组坐标
  System.out.println("用户选择图片数:" xyLocations.length);
  for (String xyLocation : xyLocations) {
   String[] xy = xyLocation.split("\|\|");
   int x = Integer.parseInt(xy[0]);
   int y = Integer.parseInt(xy[1]);

   //8,4图片区间
   if ( x > -75 && x <= 0) {

    if ( y > -75 && y <= 0) {  //8号
     list.add(8);

    } else if ( y >= -150 && y <= -75 ) {  //4号
     list.add(4);
    }
   } else if ( x > -150 && x <= -75) {  //7,3图片区间

    if ( y > -75 && y <= 0) {  //7号
     list.add(7);

    } else if ( y >= -150 && y <= -75 ) {  //3号
     list.add(3);
    }
   } else if ( x > -225 && x <= -150) {  //6,2图片区间

    if ( y > -75 && y <= 0) {  //6号
     list.add(6);

    } else if ( y >= -150 && y <= -75 ) {  //2号
     list.add(2);
    }

   } else if ( x >= -300 && x <= -225) {  //5,1图片区间

    if ( y > -75 && y <= 0) {  //5号
     list.add(5);

    } else if ( y >= -150 && y <= -75 ) {  //1号
     list.add(1);
    }
   } else {
    return null;
   }
  }
  return list;
 }

 

 

刷新生成新的图片,由于ajax不支持二进制流,可以自己用原生的xmlHttpRequest对象加html5的blob来完成。

 function refresh() {
        var url = "<%=request.getContextPath()%>/identify";
        var xhr = new XMLHttpRequest();
        xhr.open('GET', url, true);
        xhr.responseType = "blob";
        xhr.onload = function() {
            if (this.status == 200) {
                var blob = this.response;                
                //加载成功后释放blob
                bigPicture.onload = function(e) {
                    window.URL.revokeObjectURL(bigPicture.src); 
                };
                bigPicture.src = window.URL.createObjectURL(blob);
            }
        }
        xhr.send();

 验证码整体代码完成了,还有有一些细节要处理。由于图片容易被百度识图,要对生成的图片做模糊处理,暂时还没想到什么好的办法~

由于要做一个新项目,所以打算做一个简单的图片验证码。 先说说思路吧:在服务端,从一个文件...

package cn.jiguang.base64;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import jxl.Cell;
import jxl.CellType;
import jxl.NumberCell;
import jxl.Sheet;
import jxl.Workbook;
import jxl.read.biff.BiffException;

/**
 * 
 * @Description: Excel自动导出txt,构建java代码
 * @Author: zengxiaochi
 *
 * @Date: 下午11:37:27
 */
public class ExcelExport {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        String filepath = "sjd_pdl.xls";

        excelOutTxt(filepath);
    }

    private static void excelOutTxt(String filepath) {
        try {
            Workbook workbook = Workbook.getWorkbook(new File(filepath));
            Sheet sheet = workbook.getSheet("配置表");
            Sheet sheet2 = workbook.getSheet("模型逻辑");
            // rows为行数,columns列数,getCell("列号","行号")
            int rows = sheet2.getRows();
            int columns = sheet2.getColumns();
            Cell c2 = null;
            NumberCell numberCellOne = null;
            List<String> strList = new ArrayList<String>();
            List<Object> doubleList = new ArrayList<Object>();

            // 用来记录要比较的字符串

            List<String> storage = new ArrayList<String>();
            for (int i2 = 0; i2 < rows; i2 ) {
                for (int j2 = 0; j2 < columns; j2 ) {
                    // 根据横纵轴获取单元格数据
                    c2 = sheet2.getCell(j2, i2);
                    if (c2.getColumn() == 0) {
                        strList.add(c2.getContents());
                    } else if (c2.getColumn() == 1) {
                        if (CellType.NUMBER == c2.getType()) {
                            numberCellOne = (NumberCell) c2;
                            doubleList.add(numberCellOne.getValue());
                        } else {
                            doubleList.add(c2.getContents());
                        }
                    }

                }
            }
            for (Object object : doubleList) {
                System.out.println(object);
            }
            System.out.println("==============");
            for (String str : strList) {
                System.out.println(str);
            }

            File fileSuccess = new File("success.txt");
            FileWriter fwSuccess = new FileWriter(fileSuccess);
            BufferedWriter bwSuccess = new BufferedWriter(fwSuccess);

            // j为行数,getCell("列号","行号")
            int j = sheet.getRows();
            int y = sheet.getColumns();
            Cell c = null;
            NumberCell numberCell = null;           

            for (int i = 0; i < j; i ) {
                StringBuffer stringBuffer = new StringBuffer();
                for (int x = 0; x < y; x ) {
                    c = sheet.getCell(x, i);
                    if (CellType.NUMBER == c.getType()) {
                        numberCell = (NumberCell) c;
                    }

                    if (c.getColumn() == 0) {
                        storage.add(c.getContents());
                        stringBuffer.append("antifraudSjdModelEntityList.add(new AntifraudSjdModelEntity( " '"'
                                 c.getContents() '"');
                    } else if (c.getColumn() == 1 || c.getColumn() == 2) {
                        continue;
                    } else if ("inf".equals(c.getContents())) {
                        stringBuffer.append(", " "Double.MAX_VALUE");
                    } else if ("-inf".equals(c.getContents())) {
                        stringBuffer.append(", " "-Double.MAX_VALUE");
                    } else if (c.getColumn() == 5) {
                        if (CellType.NUMBER == c.getType()) {
                            stringBuffer.append(", " numberCell.getValue());
                        } else {
                            stringBuffer.append(", " c.getContents());
                        }
                    } else if (c.getColumn() == 6) {
                        for (int k = 0; k < strList.size(); k ) {
                            if (storage.get(0).trim().equals(strList.get(k).trim())) {
                                stringBuffer.append(", " doubleList.get(k) "));");
                            }
                        }
                        storage.remove(0);
                    } else if ("".equals(c.getContents())) {
                        stringBuffer.append(", " "null");
                    } else {
                        if (CellType.NUMBER == c.getType()) {
                            stringBuffer.append(", " numberCell.getValue());
                        } else {
                            stringBuffer.append(", " c.getContents());
                        }
                    }
                }

                bwSuccess.write(stringBuffer.toString());
                bwSuccess.write(" ");
                bwSuccess.flush();
                // 读取一行后换行
                bwSuccess.newLine();
                // 刷新
            }
            System.out.println("写入结束");
        } catch (BiffException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}  

本文由yzc216亚洲城发布于yzc216.com官网,转载请注明出处:逻辑条件不同实现则不同,仿12306的图片验证码

关键词: yzc216亚洲城 yzc216.com官网