资讯

精准传达 • 有效沟通

从品牌网站建设到网络营销策划,从策略到执行的一站式服务

js+java怎么实现登录滑动图片验证

这篇文章主要介绍js+java怎么实现登录滑动图片验证,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!

成都创新互联于2013年开始,先为六合等服务建站,六合等地企业,进行企业商务咨询服务。为六合企业网站制作PC+手机+微官网三网同步一站式服务解决您的所有建站问题。

下面是做出来的效果:

js+java怎么实现登录滑动图片验证

实现思路:所有的图片数据,验证全部由后端来做。前端调用接口,后端会返回两张经过base64加密的图片信息,分别是背景图片和滑块图片,前端滑动滑块以后将X方向的滑动距离传回后端做验证,验证成功以后再做后续的登录逻辑验证,以下是完整的过程:

获取背景图,我这边是在FTP上放了10张图片,随机获取一张。

@LogAnnotation(description = "web获取滑动图片信息")
 @ApiOperation(value = "web获取滑动图片信息", httpMethod = "POST", response = Result.class, notes = "")
 @RequiresPermissions(value = "code/picture/msg")
 @RequestMapping(value = "code/picture/msg", method = RequestMethod.POST)
 @ResponseBody
 public Response getPictureCode(HttpServletRequest request) {
 Map pictureMap = new HashMap<>();
 try {
 //随机获取需要切成的图片形状
 Integer templateNum = new Random().nextInt(10) + 1;
 String randomStr = String.valueOf(templateNum);
 if(templateNum < 10){
 randomStr = "0"+randomStr;
 }
 InputStream tempInputStream = FileUtils.downloadFtpFile(Constant.POCTURE_CHECK_PATH,randomStr+".jpg");
 //根据源图片和抠图形状生成新的图片信息以流的形式返回到前端
 pictureMap = VerifyImageUtil.getVerifyImage(tempInputStream);
 //将剪裁好了以后的图片信息以当前时间戳为key,存入redis(这一步是为了对图片信息做过期处理,根据自己需求做)
 String tempTime = String.valueOf(System.currentTimeMillis());
 redisUtils.hset(Constant.REDIS_LOGIN_PICTURE_CODE, tempTime,pictureMap.get("locationX").toString(),60);
 pictureMap.put("tempTime",tempTime);
 //移出随机生成的抠图位置坐标,不返回给前端
 pictureMap.remove("locationX");
 return new ObjectResponse>(pictureMap);
 }catch(Exception e){
 logger.error("code/picture/msg", e);
 return new FailedResponse();
 }
 }

FTP下载方法代码

public static FTPClient ftpLogin(){
 String ip = p.getProperty("ftp的ip");
 String username = p.getProperty("ftp的user");
 String password = p.getProperty("ftp的pwd");
 int ftpPort = Integer.parseInt(p.getProperty("ftp的port"));
  FTPClient ftpClient = new FTPClient();
 try { 
   ftpClient.connect(ip , ftpPort );// 连接FTP服务器 
   ftpClient.login(username , password );// 登陆FTP服务器 
   if (!FTPReply.isPositiveCompletion(ftpClient.getReplyCode())) { 
    ftpClient.disconnect(); 
   }
  } catch (SocketException e) { 
   e.printStackTrace(); 
  } catch (IOException e) { 
   e.printStackTrace(); 
  } 
 return ftpClient;
 }
 
public static InputStream downloadFtpFile(String ftpPath, String fileName) { 
  FTPClient ftpClient = ftpLogin();
  try {
   ftpClient.setControlEncoding("UTF-8"); // 中文支持 
   ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE); 
   ftpClient.enterLocalPassiveMode(); 
   ftpClient.changeWorkingDirectory(ftpPath); 
   InputStream inputStream = ftpClient.retrieveFileStream(new String(fileName.getBytes("UTF-8"), "ISO-8859-1"));
   //ftpClient.completePendingCommand();
   return inputStream;
  } catch (Exception e) { 
   e.printStackTrace(); 
  }finally {
   try {
 ftpClient.logout();
 } catch (IOException e) {
 e.printStackTrace();
 } 
 }
 return null;
 }

抠图工具类VerifyImageUtil

public class VerifyImageUtil {
 
 /**
 * 源文件宽度
 */
 private static int ORI_WIDTH = 296;
 /**
 * 源文件高度
 */
 private static int ORI_HEIGHT = 182;
 /**
 * 模板图宽度
 */
 private static int CUT_WIDTH = 50;
 /**
 * 模板图高度
 */
 private static int CUT_HEIGHT = 50;
 /**
 * 抠图凸起圆心
 */
 private static int circleR = 6;
 /**
 * 抠图内部矩形填充大小
 */
 private static int RECTANGLE_PADDING = 6;
 /**
 * 抠图的边框宽度
 */
 private static int SLIDER_IMG_OUT_PADDING = 1;
 
 
 /**
 * 根据传入的路径生成指定验证码图片
 *
 * @param filePath
 * @return
 * @throws IOException
 */
 public static Map getVerifyImage(InputStream filePath) throws IOException {
 BufferedImage srcImage = ImageIO.read(filePath);
 int locationX = CUT_WIDTH + new Random().nextInt(srcImage.getWidth() - CUT_WIDTH * 2);
 int locationY = CUT_HEIGHT + new Random().nextInt(srcImage.getHeight() - CUT_HEIGHT) / 2;
 BufferedImage markImage = new BufferedImage(CUT_WIDTH,CUT_HEIGHT,BufferedImage.TYPE_4BYTE_ABGR);
 int[][] data = getBlockData();
 cutImgByTemplate(srcImage, markImage, data, locationX, locationY);
 Map resultMap = new HashMap<>();
  //放入背景图的加密信息
 resultMap.put("srcImage",getImageBASE64(srcImage));
  //放入滑块图的加密信息
 resultMap.put("markImage",getImageBASE64(markImage));
  //放入抠图位置的X方向的信息,用于验证滑块位置是否正确
 resultMap.put("locationX",locationX);
  //放入抠图位置的Y方向的信息,用于前端控制定位信息
 resultMap.put("locationY",locationY);
 return resultMap;
 }
 
 
 /**
 * 生成随机滑块形状
 * 

 * 0 透明像素  * 1 滑块像素  * 2 阴影像素  * @return int[][]  */  private static int[][] getBlockData() {  int[][] data = new int[CUT_WIDTH][CUT_HEIGHT];  Random random = new Random();  //(x-a)²+(y-b)²=r²  //x中心位置左右5像素随机  double x1 = RECTANGLE_PADDING + (CUT_WIDTH - 2 * RECTANGLE_PADDING) / 2.0 - 5 + random.nextInt(10);  //y 矩形上边界半径-1像素移动  double y1_top = RECTANGLE_PADDING - random.nextInt(3);  double y1_bottom = CUT_HEIGHT - RECTANGLE_PADDING + random.nextInt(3);  double y1 = random.nextInt(2) == 1 ? y1_top : y1_bottom;      double x2_right = CUT_WIDTH - RECTANGLE_PADDING - circleR + random.nextInt(2 * circleR - 4);  double x2_left = RECTANGLE_PADDING + circleR - 2 - random.nextInt(2 * circleR - 4);  double x2 = random.nextInt(2) == 1 ? x2_right : x2_left;  double y2 = RECTANGLE_PADDING + (CUT_HEIGHT - 2 * RECTANGLE_PADDING) / 2.0 - 4 + random.nextInt(10);    double po = Math.pow(circleR, 2);  for (int i = 0; i < CUT_WIDTH; i++) {  for (int j = 0; j < CUT_HEIGHT; j++) {  //矩形区域  boolean fill;  if ((i >= RECTANGLE_PADDING && i < CUT_WIDTH - RECTANGLE_PADDING)   && (j >= RECTANGLE_PADDING && j < CUT_HEIGHT - RECTANGLE_PADDING)) {   data[i][j] = 1;   fill = true;  } else {   data[i][j] = 0;   fill = false;  }  //凸出区域  double d3 = Math.pow(i - x1, 2) + Math.pow(j - y1, 2);  if (d3 < po) {   data[i][j] = 1;  } else {   if (!fill) {   data[i][j] = 0;   }  }  //凹进区域  double d4 = Math.pow(i - x2, 2) + Math.pow(j - y2, 2);  if (d4 < po) {   data[i][j] = 0;  }  }  }  //边界阴影  for (int i = 0; i < CUT_WIDTH; i++) {  for (int j = 0; j < CUT_HEIGHT; j++) {  //四个正方形边角处理  for (int k = 1; k <= SLIDER_IMG_OUT_PADDING; k++) {   //左上、右上   if (i >= RECTANGLE_PADDING - k && i < RECTANGLE_PADDING   && ((j >= RECTANGLE_PADDING - k && j < RECTANGLE_PADDING)   || (j >= CUT_HEIGHT - RECTANGLE_PADDING - k && j < CUT_HEIGHT - RECTANGLE_PADDING +1))) {   data[i][j] = 2;   }     //左下、右下   if (i >= CUT_WIDTH - RECTANGLE_PADDING + k - 1 && i < CUT_WIDTH - RECTANGLE_PADDING + 1) {   for (int n = 1; n <= SLIDER_IMG_OUT_PADDING; n++) {   if (((j >= RECTANGLE_PADDING - n && j < RECTANGLE_PADDING)    || (j >= CUT_HEIGHT - RECTANGLE_PADDING - n && j <= CUT_HEIGHT - RECTANGLE_PADDING ))) {   data[i][j] = 2;   }   }   }  }    if (data[i][j] == 1 && j - SLIDER_IMG_OUT_PADDING > 0 && data[i][j - SLIDER_IMG_OUT_PADDING] == 0) {   data[i][j - SLIDER_IMG_OUT_PADDING] = 2;  }  if (data[i][j] == 1 && j + SLIDER_IMG_OUT_PADDING > 0 && j + SLIDER_IMG_OUT_PADDING < CUT_HEIGHT && data[i][j + SLIDER_IMG_OUT_PADDING] == 0) {   data[i][j + SLIDER_IMG_OUT_PADDING] = 2;  }  if (data[i][j] == 1 && i - SLIDER_IMG_OUT_PADDING > 0 && data[i - SLIDER_IMG_OUT_PADDING][j] == 0) {   data[i - SLIDER_IMG_OUT_PADDING][j] = 2;  }  if (data[i][j] == 1 && i + SLIDER_IMG_OUT_PADDING > 0 && i + SLIDER_IMG_OUT_PADDING < CUT_WIDTH && data[i + SLIDER_IMG_OUT_PADDING][j] == 0) {   data[i + SLIDER_IMG_OUT_PADDING][j] = 2;  }  }  }  return data;  }    /**  * 裁剪区块  * 根据生成的滑块形状,对原图和裁剪块进行变色处理  * @param oriImage 原图  * @param targetImage 裁剪图  * @param blockImage 滑块  * @param x   裁剪点x  * @param y   裁剪点y  */  private static void cutImgByTemplate(BufferedImage oriImage, BufferedImage targetImage, int[][] blockImage, int x, int y) {  for (int i = 0; i < CUT_WIDTH; i++) {  for (int j = 0; j < CUT_HEIGHT; j++) {  int _x = x + i;  int _y = y + j;  int rgbFlg = blockImage[i][j];  int rgb_ori = oriImage.getRGB(_x, _y);  // 原图中对应位置变色处理  if (rgbFlg == 1) {   //抠图上复制对应颜色值   targetImage.setRGB(i,j, rgb_ori);   //原图对应位置颜色变化   oriImage.setRGB(_x, _y, rgb_ori & 0x363636);  } else if (rgbFlg == 2) {   targetImage.setRGB(i, j, Color.WHITE.getRGB());   oriImage.setRGB(_x, _y, Color.GRAY.getRGB());  }else if(rgbFlg == 0){   //int alpha = 0;   targetImage.setRGB(i, j, rgb_ori & 0x00ffffff);  }  }    }  }      /**  * 随机获取一张图片对象  * @param path  * @return  * @throws IOException  */  public static BufferedImage getRandomImage(String path) throws IOException {  File files = new File(path);  File[] fileList = files.listFiles();  List fileNameList = new ArrayList<>();  if (fileList!=null && fileList.length!=0){  for (File tempFile:fileList){  if (tempFile.isFile() && tempFile.getName().endsWith(".jpg")){   fileNameList.add(tempFile.getAbsolutePath().trim());  }  }  }  Random random = new Random();  File imageFile = new File(fileNameList.get(random.nextInt(fileNameList.size())));  return ImageIO.read(imageFile);  }    /**  * 将IMG输出为文件  * @param image  * @param file  * @throws Exception  */  public static void writeImg(BufferedImage image, String file) throws Exception {  byte[] imagedata = null;  ByteArrayOutputStream bao=new ByteArrayOutputStream();  ImageIO.write(image,"png",bao);  imagedata = bao.toByteArray();  FileOutputStream out = new FileOutputStream(new File(file));  out.write(imagedata);  out.close();  }    /**  * 将图片转换为BASE64  * @param image  * @return  * @throws IOException  */  public static String getImageBASE64(BufferedImage image) throws IOException {  ByteArrayOutputStream out = new ByteArrayOutputStream();  ImageIO.write(image,"png",out);  //转成byte数组  byte[] bytes = out.toByteArray();  BASE64Encoder encoder = new BASE64Encoder();  //生成BASE64编码  return encoder.encode(bytes);  }    /**  * 将BASE64字符串转换为图片  * @param base64String  * @return  */  public static BufferedImage base64StringToImage(String base64String) {  try {  BASE64Decoder decoder=new BASE64Decoder();  byte[] bytes1 = decoder.decodeBuffer(base64String);  ByteArrayInputStream bais = new ByteArrayInputStream(bytes1);  return ImageIO.read(bais);  } catch (IOException e) {  e.printStackTrace();  }  return null;  } }

前端收到请求成功返回信息以后,对数据做解析

js+java怎么实现登录滑动图片验证

// 设置图片的src属性
 $("#背景图的ID").attr("src", "data:image/png;base64," + result.datas.srcImage);
 $("#滑块图的ID").attr("src", "data:image/png;base64," + result.datas.markImage);
 $("#滑块图的ID").css("top", result.datas.locationY);
 /* 初始化按钮拖动事件 */
 // 鼠标点击事件
 $("#滑块拖动条").mousedown(function(e) {
  e = e || window.event;
  // 鼠标在滑块按下切换滑块背景
  var left = e.pageX;//记录鼠标按下时的坐标 X轴值
  var num = 0;
  // 鼠标移动事件
  document.onmousemove = function(e) {
  var nowLeft = e.pageX;
  num = nowLeft-left;
  if(num <= 0){
  num = 0;
  }else if(num >= 251){
  num= 251;
  }
  $("#滑块拖动条").css("width", (42+num) + "px");
  $("#滑块拖动条图片").css("left", (num) + "px");
  $("#滑块拖动条").css("background-color", "#3c55ff");
  };
  // 鼠标松开事件
  document.onmouseup = function(e) {
  left = 0;
  document.onmousemove = null;
  document.onmouseup = null;
      //松开以后进行后续的验证......
  
  };
 });

以上是“js+java怎么实现登录滑动图片验证”这篇文章的所有内容,感谢各位的阅读!希望分享的内容对大家有帮助,更多相关知识,欢迎关注创新互联行业资讯频道!


分享文章:js+java怎么实现登录滑动图片验证
文章源于:http://cdkjz.cn/article/jepeho.html
多年建站经验

多一份参考,总有益处

联系快上网,免费获得专属《策划方案》及报价

咨询相关问题或预约面谈,可以通过以下方式与我们联系

业务热线:400-028-6601 / 大客户专线   成都:13518219792   座机:028-86922220