国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > Java > 正文

Java仿12306圖片驗證碼

2019-11-26 14:26:46
字體:
來源:轉載
供稿:網友

由于要做一個新項目,所以打算做一個簡單的圖片驗證碼。

先說說思路吧:在服務端,從一個文件夾里面找出8張圖片,再把8張圖片合并成一張大圖,在8個小圖里面隨機生成一個要用戶驗證的圖片分類,如小狗、啤酒等。在前端,訪問這個頁面時,把圖片加載上去,用戶在圖片上選擇提示所需要的圖片,當用戶點登陸時,根據用戶選擇的所有坐標判斷所選的圖片是不是實際上的驗證圖片。

先放兩張效果圖:

為了讓文件查找比較簡單,在圖片文件結構上可以這樣:

這樣方便生成用戶要選擇的Key圖片,和取出8張小圖合并成大圖。

上代碼:這是選擇8張圖片,并且在每張圖片選取時用遞歸保證選取的圖片不會重復。

//選取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><br>  <div id="base"><br>   <img src="<%=request.getContextPath()%>/identify" style="width: 300px; height: 150px;" onclick="clickImg(event)" id="bigPicture"><br>  </div><br>  <br> </div><br><br>function clickImg(e) {  var baseDiv = document.getElementById("base");  var topValue = 0;  var leftValue = 0;  var obj = baseDiv;  while (obj) {   leftValue += obj.offsetLeft;   topValue +=obj.offsetTop;   obj = obj.offsetParent;  }  //解決firefox獲取不到點擊事件的問題  var clickEvent = e ? e : (window.event ? window.event : null);      var clickLeft = clickEvent.clientX + document.body.scrollLeft - document.body.clientLeft - 10;  var clickTop = clickEvent.clientY + document.body.scrollTop - document.body.clientTop - 10;  var divId = "img_" + index++;    var divEle = document.createElement("div");    divEle.setAttribute("id", divId);  divEle.style.position = "relative";  divEle.style.zIndex = index;  divEle.style.width = "20px";  divEle.style.height = "20px";  divEle.style.display = "inline";    divEle.style.top = clickTop - topValue - 150 + 10 + "px";  divEle.style.left = clickLeft - leftValue - 300 + "px";    divEle.setAttribute("onclick", "remove('" + divId + "')");  baseDiv.appendChild(divEle);    var imgEle = document.createElement("img");  imgEle.src = "<%=request.getContextPath()%>/resources/timo.png";  imgEle.style.width = "20px";  imgEle.style.height = "20px";  imgEle.style.top = "0px";  imgEle.style.left = "0px";  imgEle.style.position = "absolute";  imgEle.style.zIndex = index;  divEle.appendChild(imgEle); }

用戶選擇登錄后,服務器端根據用戶的選擇坐標進行判斷

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("http://|//|");   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();

 驗證碼整體代碼完成了,還有有一些細節要處理。

以上就是本文的全部內容,希望對大家的學習有所幫助。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 普兰店市| 黄龙县| 班玛县| 高邑县| 永宁县| 惠东县| 台安县| 塔河县| 金阳县| 泰顺县| 什邡市| 怀来县| 辉南县| 吴江市| 曲阜市| 桐梓县| 登封市| 娱乐| 台湾省| 通道| 遂溪县| 杨浦区| 克拉玛依市| 鞍山市| 清远市| 姚安县| 彩票| 梁山县| 云南省| 黄龙县| 保山市| 河源市| 咸宁市| 梓潼县| 镇江市| 南华县| 凤阳县| 霍州市| 桃江县| 正定县| 江陵县|