成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

慕課網(wǎng)_《Java圖片驗(yàn)證碼》學(xué)習(xí)總結(jié)

haitiancoder / 3424人閱讀

時(shí)間:2017年07月09日星期日
說明:本文部分內(nèi)容均來自慕課網(wǎng)。@慕課網(wǎng):http://www.imooc.com
教學(xué)源碼:無
學(xué)習(xí)源碼:https://github.com/zccodere/s...

第一章:概述 1-1 課程概述

主要內(nèi)容

驗(yàn)證碼歷史
課程內(nèi)容
不同方案對(duì)比
設(shè)計(jì)與實(shí)現(xiàn)
總結(jié)
1-2 驗(yàn)證碼歷史

驗(yàn)證碼歷史

無驗(yàn)證碼:垃圾騷擾
Luis von Ahn:Captcha
不斷的升級(jí)
去驗(yàn)證碼

常見驗(yàn)證碼

1-3 項(xiàng)目介紹

完成類似最后一張圖片的驗(yàn)證碼設(shè)計(jì)與實(shí)現(xiàn)

對(duì)比方案
完成設(shè)計(jì)
編碼實(shí)現(xiàn)
結(jié)果演示

結(jié)果演示

不同方案對(duì)比(一)

瀏覽器請(qǐng)求驗(yàn)證碼圖片
服務(wù)器返回驗(yàn)證碼圖片及圖片標(biāo)識(shí)
瀏覽器提交驗(yàn)證碼
服務(wù)器驗(yàn)證圖片內(nèi)容及標(biāo)識(shí)

不同方案對(duì)比(二)

瀏覽器請(qǐng)求驗(yàn)證碼圖片
服務(wù)器返回驗(yàn)證碼圖片及圖片標(biāo)識(shí)
瀏覽器提交驗(yàn)證碼
    圖片文字/計(jì)算結(jié)果等
    坐標(biāo)
服務(wù)器驗(yàn)證
    驗(yàn)證圖片內(nèi)容及標(biāo)識(shí)
    驗(yàn)證坐標(biāo)及標(biāo)識(shí)

設(shè)計(jì)與實(shí)現(xiàn)

包結(jié)構(gòu)
--controller、generator
主要類及作用
--Image:生成驗(yàn)證碼圖片核心類
--BufferedImageWrap:圖片包裝類
--ImageGroup:原始圖片分組
--GenerateImageGroup:?jiǎn)未悟?yàn)證使用圖片組
--Cache:?jiǎn)未悟?yàn)證數(shù)據(jù)緩存
--LoginController

程序設(shè)計(jì):技術(shù)選擇
教學(xué)使用

SpringMVC
JSP
Spring(4.0.5)

學(xué)習(xí)使用

SpringBoot
Freemarker

思路整理

每次顯示幾張圖片:由8張小圖組成的一張大圖
答案圖片位置
選中位置坐標(biāo)
坐標(biāo)驗(yàn)證
前后關(guān)聯(lián)
第二章:圖片生成及頁面顯示 2-1 頁面結(jié)構(gòu)及LoginController介紹

部分代碼演示:源碼請(qǐng)到我的github地址查看

login.html



登錄






    
    
郵箱/用戶名/手機(jī)號(hào)

密碼

選出圖片中的"${tip}"

LoginController類

package com.myimooc.identifying.controller;

import java.io.IOException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import com.myimooc.identifying.generator.Image;
import com.myimooc.identifying.generator.ImageResult;

/**
 * 登錄控制器
 * @author ZhangCheng on 2017-07-09
 *
 */
@Controller
public class LoginController {
    
    /**
     * 登錄主頁
     * @param model
     * @param request
     * @param response
     * @return
     */
    @RequestMapping("/login")
    public String identify(Model model,HttpServletRequest request,HttpServletResponse response){
        try{
            ImageResult imageResult  = Image.generateImage();
            model.addAttribute("file", imageResult.getName());
            model.addAttribute("tip", imageResult.getTip());
            System.out.println(imageResult.getName() + imageResult.getTip());
            Cookie cookie = new Cookie("note",imageResult.getUniqueKey());
            response.addCookie(cookie);
            request.getSession().setAttribute(imageResult.getUniqueKey(), imageResult);
        }catch(Exception e){
            System.out.println("獲取圖片失敗");
            e.printStackTrace();
        }
        return "login";
    }
    
     /**
     * 刷新圖片
     *
     * @param request
     * @return
     * @throws IOException
     */
    @RequestMapping(value = "/getPng")
    @ResponseBody
    public String getPng(HttpServletRequest request) throws IOException{
        ImageResult imageResult = Image.generateImage();
        ((HttpServletRequest) request).getSession().setAttribute("imageResult", imageResult);
        return imageResult.getName() + "," + imageResult.getTip();
    }
    
    /**
     * 驗(yàn)證消息
     *
     * @param location
     * @param request
     * @param userName
     * @param password
     * @return
     */
    @PostMapping("/dologin")
    @ResponseBody
    public String doLogin(String location, HttpServletRequest request, String userName, String password, RedirectAttributes redirectAttributes) {
        System.out.println("驗(yàn)證坐標(biāo):"+ location);
        Cookie[] cookies = ((HttpServletRequest) request).getCookies();
        Cookie note = null;
        for (Cookie cookie : cookies) {
            if (cookie.getName().equals("note")) {
                note = cookie;
                break;
            }
        }
        
        if(null == note){
            return "ERROR";
        }
        
        ImageResult imageResult = (ImageResult)request.getSession().getAttribute(note.getValue());
        
        if(validate(location,imageResult)){
            return "OK";
        }
        
        return "ERROR";
    }
    /**
     * 驗(yàn)證是否正確
     * @param locationString
     * @param imageResult
     * @return
     */
    private boolean validate(String locationString, ImageResult imageResult) {
        
        String[] resultArray = locationString.split(";");
        int[][] array = new int[resultArray.length][2];
        for (int i = 0; i=0 && y<75){
            return xLocation(x);
        }else if(y >=75 && y<=150){
            return xLocation(x)+4;
        }else{
            // 臟數(shù)據(jù)
            return -1;
        }
    }

    private int xLocation(int x) {
        if(x >=0 && x<75){
            return 0;
        }else if(x >=75 && x<150){
            return 1;
        }else if(x >=150 && x<225){
            return 2;
        }else if(x >=225 && x<=300){
            return 3;
        }else{
            // 臟數(shù)據(jù)
            return -1;
        }
    }
}
2-2 如何生成圖片generateImage

Image類

package com.myimooc.identifying.generator;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.UUID;

import javax.imageio.ImageIO;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 生成驗(yàn)證碼圖片核心類
 * @author ZhangCheng on 2017-07-09
 *
 */
public class Image {
    
    private static final Logger log= LoggerFactory.getLogger(Image.class);

    private static Map imageGroupMap=new HashMap<>();
    private static Map> countGroupMap=new HashMap<>();
    
    /**
     * 功能:由小圖生成一種大圖
     * @return
     * @throws IOException
     */
    public static ImageResult generateImage()throws IOException{
        // 初始化
        initImageGroup();
        log.debug("初始化完成");
        GenerateImageGroup generateImageGroup = randomImageGroups();
        List images = new ArrayList();
        // 找到圖片干擾項(xiàng)
        for (ImageGroup group : generateImageGroup.getGroups()) {
            for (String imgName : group.getImages()) {
                images.add(new BufferedImageWrap(false,getBufferedImage(imgName)));
            }
        }
        // 找到圖片答案項(xiàng)
        for(String imgName : generateImageGroup.getKeyGroup().getImages()){
            images.add(new BufferedImageWrap(true,getBufferedImage(imgName)));
        }
        return mergeImage(images,generateImageGroup.getKeyGroup().getName());
    }

    /**
     * 功能:根據(jù)圖片名稱獲得圖片緩沖流
     * @param imgName
     * @return
     * @throws IOException
     */
    private static BufferedImage getBufferedImage(String imgName)throws IOException {
        String rootPath = Image.class.getClassLoader().getResource("sourceImage/").getPath();
        String imgPath = rootPath + imgName;
        File file = new File(imgPath);
        return ImageIO.read(file);
    }
    
    /**
     * 功能:將小圖合并成一種大圖
     * @param images
     * @param name
     * @return
     */
    private static ImageResult mergeImage(List imageWraps, String tip) {
        Collections.shuffle(imageWraps);
        // 原始圖片寬200像素,高200像素
        int width = 200;
        int high = 200;
        int totalWidth = width * 4;
        
        BufferedImage destImage = new BufferedImage(totalWidth,400,BufferedImage.TYPE_INT_RGB);
        int x1 = 0;
        int x2 = 0;
        int order = 0;
        List keysOrderList = new ArrayList();
        StringBuilder keysOrder = new StringBuilder();
        Set keySet = new HashSet();
        for(BufferedImageWrap image : imageWraps){
            int[] rgb = image.getBufferedImage().getRGB(0, 0, width, high, null, 0, width);
            if(image.isKey()){
                keysOrderList.add(order);
                int x = (order % 4) * 200;
                int y = order < 4 ? 0:200;
                keySet.add(order);
                keysOrder.append(order).append("(").append(x).append(",").append(y).append(")|");
            }
            if(order < 4 ){
                // 設(shè)置上半部分的RGB
                destImage.setRGB(x1, 0, width,high,rgb,0,width);
                x1 += width;
            }else{
                destImage.setRGB(x2, high, width,high,rgb,0,width);
                x2 += width;
            }
            order++;
        }
        
        keysOrder.deleteCharAt(keysOrder.length() - 1);
        System.out.println("答案位置:" + keysOrder);
        String fileName = UUID.randomUUID().toString().replaceAll("-", "") + ".jpeg";
        String rootPath = Image.class.getClassLoader().getResource("static/targetImage/").getPath();
        //String rootPath = Image.class.getClassLoader().getResource("sourceImage/").getPath();
        log.info("根路徑:{}",rootPath);
        String fileUrl = rootPath + fileName;
        // 保存圖片
        saveImage(destImage,fileUrl,"png");
        
        ImageResult ir = new ImageResult();
        ir.setName(fileName);
        ir.setKeySet(keySet);
        ir.setUniqueKey(fileName);
        ir.setTip(tip);
        return ir;
    }
    
    /**
     * 功能:將圖片寫入指定的路徑
     * @param destImage
     * @param fileUrl
     * @param string
     */
    private static void saveImage(BufferedImage destImage, String fileUrl, String format) {
        File file=new File(fileUrl);
        log.debug(file.getAbsolutePath());
        try {
            ImageIO.write(destImage,format,file);
        } catch (IOException e) {
            log.info("圖片寫入失敗");
            e.printStackTrace();
        }
    }

    /**
     * 功能:隨機(jī)生成圖片答案和干擾組
     * @return
     */
    private static GenerateImageGroup randomImageGroups(){
        
        List result = new ArrayList();
        int num = random(0, imageGroupMap.size() - 1);
        
        String name = new ArrayList(imageGroupMap.keySet()).get(num);
        ImageGroup keyGroup = imageGroupMap.get(name);
        
        Map> thisCountGroupMap = new HashMap<>(countGroupMap);
        thisCountGroupMap.get(keyGroup.getCount()).remove(name);
        
        // 假設(shè)總量8個(gè),每種名稱圖片只有2個(gè)或4個(gè),為了邏輯簡(jiǎn)單些
        int leftCount = 8 - keyGroup.getCount();
        if(leftCount == 4){
            if(new Random().nextInt() % 2 == 0){
                List groups = new ArrayList(thisCountGroupMap.get(4).values());
                if(groups.size() > 1){
                    num = random(0, groups.size() - 1);
                }else{
                    num = 0;
                }
                result.add(groups.get(num));
            }else{
                List groups = new ArrayList(thisCountGroupMap.get(2).values());
                int num1 = random(0, groups.size() - 1);
                result.add(groups.get(num1));
                
                int num2 = random(0, groups.size() - 1,num1);
                result.add(groups.get(num2));
            }
        }else if(leftCount == 6){
            if(new Random().nextInt() % 2 == 0){
                List groups1 = new ArrayList(thisCountGroupMap.get(4).values());
                int num1 = random(0, groups1.size() - 1);
                result.add(groups1.get(num1));
                
                List groups2 = new ArrayList(thisCountGroupMap.get(2).values());
                int num2 = random(0, groups2.size() - 1);
                result.add(groups2.get(num2));
            }else{
                List groups = new ArrayList(thisCountGroupMap.get(2).values());
                int num1 = random(0, groups.size() - 1);
                result.add(groups.get(num1));
                
                int num2 = random(0, groups.size() - 1,num1);
                result.add(groups.get(num2));
                
                int num3 = random(0, groups.size() - 1,num1,num2);
                result.add(groups.get(num3));
            }
        }
        
        return new GenerateImageGroup(keyGroup, result);
        
    }
    
    /**
     * 功能:初始化圖片組。后期優(yōu)化可從數(shù)據(jù)庫獲取
     */
    private static void initImageGroup(){
        ImageGroup group1 = new ImageGroup("包包",4,"bao/1.jpg","bao/2.jpg","bao/3.jpg","bao/4.jpg");
        ImageGroup group2 = new ImageGroup("老虎",4,"laohu/1.jpg","laohu/2.jpg","laohu/3.jpg","laohu/4.jpg");
        ImageGroup group3 = new ImageGroup("糖葫蘆",4,"tanghulu/1.jpg","tanghulu/2.jpg","tanghulu/3.jpg","tanghulu/4.jpg");
        ImageGroup group4 = new ImageGroup("小慕",4,"xiaomu/1.jpg","xiaomu/2.jpg","xiaomu/3.jpg","xiaomu/4.jpg");
        ImageGroup group5 = new ImageGroup("柚子",4,"youzi/1.jpg","youzi/2.jpg","youzi/3.jpg","youzi/4.jpg");
        ImageGroup group6 = new ImageGroup("訂書機(jī)",2,"dingshuji/1.jpg","dingshuji/2.jpg");
        ImageGroup group7 = new ImageGroup("蘑菇",2,"mogu/1.jpg","mogu/2.jpg");
        ImageGroup group8 = new ImageGroup("磁鐵",2,"citie/1.jpg","citie/2.jpg");
        ImageGroup group9 = new ImageGroup("土豆",4,"tudou/1.jpg","tudou/2.jpg","tudou/3.jpg","tudou/4.jpg");
        ImageGroup group10 = new ImageGroup("兔子",4,"tuzi/1.jpg","tuzi/2.jpg","tuzi/3.jpg","tuzi/4.jpg");
        ImageGroup group11 = new ImageGroup("仙人球",4,"xianrenqiu/1.jpg","xianrenqiu/2.jpg","xianrenqiu/3.jpg","xianrenqiu/4.jpg");
        
        initMap(group1,group2,group3,group4,group5,group6,group7,group8,group9,group10,group11);
    }
    
    /**
     * 功能:初始化所有圖片組
     * @param groups
     */
    private static void initMap(ImageGroup... groups) {
        for (ImageGroup group : groups) {
            imageGroupMap.put(group.getName(),group);
            if(!countGroupMap.containsKey(group.getCount())){
                countGroupMap.put(group.getCount(),new HashMap());
            }
            countGroupMap.get(group.getCount()).put(group.getName(),group);
        }
    }
    
    /**
     * 功能:生成隨機(jī)整數(shù)
     * @param min
     * @param max
     * @return
     */
    private static int random(int min,int max){
        Random random = new Random();
        return random.nextInt(max - min + 1) + min;
    }
    
    /**
     * 功能:生成隨機(jī)整數(shù)不在指定整數(shù)數(shù)組里
     * @param min
     * @param max
     * @param not
     * @return
     */
    private static int random(int min,int max,Integer... not){
        int num = random(min,max);
        List notList = Arrays.asList(not);
        while(notList.contains(num)){
            num = random(min,max);
        }
        return num;
    }
}
2-3 如何將圖片融合mergeImage
/**
     * 功能:將小圖合并成一種大圖
     * @param images
     * @param name
     * @return
     */
    private static ImageResult mergeImage(List imageWraps, String tip) {
        Collections.shuffle(imageWraps);
        // 原始圖片寬200像素,高200像素
        int width = 200;
        int high = 200;
        int totalWidth = width * 4;
        
        BufferedImage destImage = new BufferedImage(totalWidth,400,BufferedImage.TYPE_INT_RGB);
        int x1 = 0;
        int x2 = 0;
        int order = 0;
        List keysOrderList = new ArrayList();
        StringBuilder keysOrder = new StringBuilder();
        Set keySet = new HashSet();
        for(BufferedImageWrap image : imageWraps){
            int[] rgb = image.getBufferedImage().getRGB(0, 0, width, high, null, 0, width);
            if(image.isKey()){
                keysOrderList.add(order);
                int x = (order % 4) * 200;
                int y = order < 4 ? 0:200;
                keySet.add(order);
                keysOrder.append(order).append("(").append(x).append(",").append(y).append(")|");
            }
            if(order < 4 ){
                // 設(shè)置上半部分的RGB
                destImage.setRGB(x1, 0, width,high,rgb,0,width);
                x1 += width;
            }else{
                destImage.setRGB(x2, high, width,high,rgb,0,width);
                x2 += width;
            }
            order++;
        }
        
        keysOrder.deleteCharAt(keysOrder.length() - 1);
        System.out.println("答案位置:" + keysOrder);
        String fileName = UUID.randomUUID().toString().replaceAll("-", "") + ".jpeg";
        String rootPath = Image.class.getClassLoader().getResource("static/targetImage/").getPath();
        //String rootPath = Image.class.getClassLoader().getResource("sourceImage/").getPath();
        log.info("根路徑:{}",rootPath);
        String fileUrl = rootPath + fileName;
        // 保存圖片
        saveImage(destImage,fileUrl,"png");
        
        ImageResult ir = new ImageResult();
        ir.setName(fileName);
        ir.setKeySet(keySet);
        ir.setUniqueKey(fileName);
        ir.setTip(tip);
        return ir;
    }
    
    /**
     * 功能:將圖片寫入指定的路徑
     * @param destImage
     * @param fileUrl
     * @param string
     */
    private static void saveImage(BufferedImage destImage, String fileUrl, String format) {
        File file=new File(fileUrl);
        log.debug(file.getAbsolutePath());
        try {
            ImageIO.write(destImage,format,file);
        } catch (IOException e) {
            log.info("圖片寫入失敗");
            e.printStackTrace();
        }
    }
第三章:驗(yàn)證過程及總結(jié) 3-1 驗(yàn)證驗(yàn)證碼過程及總結(jié)

總結(jié)

驗(yàn)證碼歷史
不同方案對(duì)比
設(shè)計(jì)與實(shí)現(xiàn)
總結(jié)

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/67325.html

相關(guān)文章

  • 課網(wǎng)_Java生成二維學(xué)習(xí)總結(jié)

    摘要:時(shí)間年月日星期五說明本文部分內(nèi)容均來自慕課網(wǎng)。線性堆疊式二維碼示意圖矩陣式二維碼在一個(gè)矩形空間通過黑白像素在矩陣中的不同分布進(jìn)行編碼。 時(shí)間:2017年06月23日星期五說明:本文部分內(nèi)容均來自慕課網(wǎng)。@慕課網(wǎng):http://www.imooc.com教學(xué)示例源碼:無個(gè)人學(xué)習(xí)源碼:https://github.com/zccodere/s... 第一章:二維碼的概念 1-1 二維碼概述...

    QLQ 評(píng)論0 收藏0
  • 課網(wǎng)_Java實(shí)現(xiàn)Base64加密》學(xué)習(xí)總結(jié)

    摘要:時(shí)間年月日星期一說明本文部分內(nèi)容均來自慕課網(wǎng)。多用于網(wǎng)絡(luò)加密。散列函數(shù)函數(shù)或消息摘要函數(shù)主要作用散列函數(shù)用來驗(yàn)證數(shù)據(jù)的完整性。 時(shí)間:2017年4月10日星期一說明:本文部分內(nèi)容均來自慕課網(wǎng)。@慕課網(wǎng):http://www.imooc.com教學(xué)示例源碼:https://github.com/zccodere/s...個(gè)人學(xué)習(xí)源碼:https://github.com/zccodere...

    verano 評(píng)論0 收藏0
  • 課網(wǎng)_《Spring Boot 發(fā)送郵件》學(xué)習(xí)總結(jié)

    摘要:慕課網(wǎng)發(fā)送郵件學(xué)習(xí)總結(jié)時(shí)間年月日星期六說明本文部分內(nèi)容均來自慕課網(wǎng)。 慕課網(wǎng)《Spring Boot 發(fā)送郵件》學(xué)習(xí)總結(jié) 時(shí)間:2018年09月08日星期六 說明:本文部分內(nèi)容均來自慕課網(wǎng)。@慕課網(wǎng):https://www.imooc.com 教學(xué)源碼:https://github.com/ityouknow/... 學(xué)習(xí)源碼:https://github.com/zccoder...

    Meathill 評(píng)論0 收藏0
  • 課網(wǎng)_《初識(shí)Java微信公眾號(hào)開發(fā)》學(xué)習(xí)總結(jié)

    摘要:時(shí)間年月日星期五說明本文部分內(nèi)容均來自慕課網(wǎng)。本套課程介紹微信公眾號(hào)開發(fā),主要涉及公眾號(hào)介紹編輯模式介紹開發(fā)模式介紹等。慕課網(wǎng)是垂直的互聯(lián)網(wǎng)技能免費(fèi)學(xué)習(xí)網(wǎng)站。 時(shí)間:2017年08月11日星期五說明:本文部分內(nèi)容均來自慕課網(wǎng)。@慕課網(wǎng):http://www.imooc.com教學(xué)源碼:https://github.com/zccodere/s...學(xué)習(xí)源碼:https://github...

    PrototypeZ 評(píng)論0 收藏0
  • 課網(wǎng)_Java實(shí)現(xiàn)郵箱驗(yàn)證學(xué)習(xí)總結(jié)

    摘要:時(shí)間年月日星期三說明本文部分內(nèi)容均來自慕課網(wǎng)。用戶過生日,系統(tǒng)發(fā)送生日祝福郵件。將最新活動(dòng)和優(yōu)惠以郵件的形式告知會(huì)員。通常把處理用戶請(qǐng)求郵件發(fā)送請(qǐng)求的郵件服務(wù)器稱為服務(wù)器。提供了加密的協(xié)議被稱為。 時(shí)間:2017年06月07日星期三說明:本文部分內(nèi)容均來自慕課網(wǎng)。@慕課網(wǎng):http://www.imooc.com教學(xué)示例源碼:無個(gè)人學(xué)習(xí)源碼:https://github.com/zcc...

    marser 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<