天天看點

JAVA實作圖檔驗證

一、什麼是圖檔驗證碼?

可以參考下面這張圖:

JAVA實作圖檔驗證

我們在一些網站登陸的時候,經常需要填寫以上圖檔的資訊。

這種圖檔驗證方式是我們最常見的形式,它可以有效的防範惡意攻擊者采用惡意工具,來進行竊取使用者的密碼

接下來将講正題啦!

1.首先得有一個生成圖檔驗證碼的實體類

package com.zhetian.www.util;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Random;

/**
 * @Copyright (C)遮天網絡有限公司
 * @Author: YUAN HUAI XING
 * @qq聯系方式: 11234013
 * @Date 2020/4/5 18:09
 * @Descripthion:
 **/

public class ImageVerificationCodeUtil {
    private int weight = 100;           //驗證碼圖檔的長和寬
    private int height = 40;
    private String text;                //用來儲存驗證碼的文本内容
    private Random r = new Random();    //擷取随機數對象
    //private String[] fontNames = {"宋體", "華文楷體", "黑體", "微軟雅黑", "楷體_GB2312"};   //字型數組
    //字型數組
    private String[] fontNames = {"Georgia"};
    //驗證碼數組
    private String codes = "23456789abcdefghjkmnopqrstuvwxyzABCDEFGHJKMNPQRSTUVWXYZ";

    /**
     * 擷取随機的顔色
     *
     * @return
     */
    private Color randomColor() {
        int r = this.r.nextInt(225);  //這裡為什麼是225,因為當r,g,b都為255時,即為白色,為了好辨認,需要顔色深一點。
        int g = this.r.nextInt(225);
        int b = this.r.nextInt(225);
        return new Color(r, g, b);            //傳回一個随機顔色
    }

    /**
     * 擷取随機字型
     *
     * @return
     */
    private Font randomFont() {
        int index = r.nextInt(fontNames.length);  //擷取随機的字型
        String fontName = fontNames[index];
        int style = r.nextInt(4);         //随機擷取字型的樣式,0是無樣式,1是加粗,2是斜體,3是加粗加斜體
        int size = r.nextInt(10) + 24;    //随機擷取字型的大小
        return new Font(fontName, style, size);   //傳回一個随機的字型
    }

    /**
     * 擷取随機字元
     *
     * @return
     */
    private char randomChar() {
        int index = r.nextInt(codes.length());
        return codes.charAt(index);
    }

    /**
     * 畫幹擾線,驗證碼幹擾線用來防止計算機解析圖檔
     *
     * @param image
     */
    private void drawLine(BufferedImage image) {
        int num = r.nextInt(10); //定義幹擾線的數量
        Graphics2D g = (Graphics2D) image.getGraphics();
        for (int i = 0; i < num; i++) {
            int x1 = r.nextInt(weight);
            int y1 = r.nextInt(height);
            int x2 = r.nextInt(weight);
            int y2 = r.nextInt(height);
            g.setColor(randomColor());
            g.drawLine(x1, y1, x2, y2);
        }
    }

    /**
     * 建立圖檔的方法
     *
     * @return
     */
    private BufferedImage createImage() {
        //建立圖檔緩沖區
        BufferedImage image = new BufferedImage(weight, height, BufferedImage.TYPE_INT_RGB);
        //擷取畫筆
        Graphics2D g = (Graphics2D) image.getGraphics();
        //設定背景色随機
        g.setColor(new Color(255, 255, r.nextInt(245) + 10));
        g.fillRect(0, 0, weight, height);
        //傳回一個圖檔
        return image;
    }

    /**
     * 擷取驗證碼圖檔的方法
     *
     * @return
     */
    public BufferedImage getImage() {
        BufferedImage image = createImage();
        Graphics2D g = (Graphics2D) image.getGraphics(); //擷取畫筆
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < 4; i++)             //畫四個字元即可
        {
            String s = randomChar() + "";      //随機生成字元,因為隻有畫字元串的方法,沒有畫字元的方法,是以需要将字元變成字元串再畫
            sb.append(s);                      //添加到StringBuilder裡面
            float x = i * 1.0F * weight / 4;   //定義字元的x坐标
            g.setFont(randomFont());           //設定字型,随機
            g.setColor(randomColor());         //設定顔色,随機
            g.drawString(s, x, height - 5);
        }
        this.text = sb.toString();
        drawLine(image);
        return image;
    }


    /**
     * 擷取驗證碼文本的方法
     *
     * @return
     */
    public String getText() {
        return text;
    }

    public static void output(BufferedImage image, OutputStream out) throws IOException                  //将驗證碼圖檔寫出的方法
    {
        ImageIO.write(image, "JPEG", out);
    }

}      

2.在控制器中把圖檔響應給前端頁面(ssm架構)

/**
     * 圖檔随機碼
     * @param request
     * @param response
     * @throws IOException
     */
    @RequestMapping("/getVerifiCode")
    public void getVerifiCode(HttpServletRequest request, HttpServletResponse response) throws IOException {
        /*
             1.生成驗證碼
             2.把驗證碼上的文本存在session中
             3.把驗證碼圖檔發送給用戶端
             */
        ImageVerificationCodeUtil ivc = new ImageVerificationCodeUtil();     //用我們的驗證碼類,生成驗證碼類對象
        BufferedImage image = ivc.getImage();  //擷取驗證碼
        String text = ivc.getText(); //擷取随機碼
        HttpSession session = request.getSession();
        session.setAttribute("imgcode", text); //将随機碼的文本存在session中
        System.out.println("文字随機碼:"+text);
        ImageVerificationCodeUtil.output(image, response.getOutputStream());//将驗證碼圖檔響應給用戶端
    }      
3、從session獲得驗證碼字元(ssm架構)
      
/**
     * 登陸功能:接收使用者輸入的使用者名跟密碼(接收參數)
     * @param loginUser
     * @return
     */
    @RequestMapping("/pageData")
    @ResponseBody
    public Result pageData(LoginUser loginUser,String code,HttpServletRequest request){
        HttpSession session = request.getSession();
        //擷取随機數
        String imgcode = (String)session.getAttribute("imgcode");
        //調用業務方法
        Result<LoginUser> result= loginUserService.loginUserByuserName(loginUser, code,imgcode);
        return result;
    }      
4、業務層(Service)
      
/**
     * 擷取使用者輸入的使用者名與資料庫進行對比是否一緻
     * 如果一緻在擷取密碼對比是否一緻
     * 都一緻再對比圖檔驗證碼與使用者輸入的是否一緻
     * @param loginUser
     * @return
     */
    @Override
    public Result loginUserByuserName(LoginUser loginUser,String code,String imgcode) {
        Result<LoginUser> result = new Result<>();
        String userName = loginUser.getUserName();
        LoginUser loginUser1 = loginUserDao.loginUserByuserName(userName);
        if (code != null && code.equals(imgcode)) {
            if (loginUser1 != null) {
                String password = loginUser.getPassword();
                String password1 = loginUser1.getPassword();
                if (password != null && password1 != null && password1.equals(password)) {
                    result.setCode("0000");
                    result.setData(loginUser);
                    return result;
                } else {
                    result.setCode("0001");
                    result.setMsg("使用者名或密碼錯誤!請檢查後重新登陸!");
                    result.setSuccess(false);
                    return result;
                }
            } else {
                result.setCode("0002");
                result.setMsg("使用者名不存在!請檢查使用者名後重新登陸!");
                result.setSuccess(false);
                return result;
            }
        }else {
            result.setCode("0005");
            result.setMsg("驗證碼不正确!");
            result.setSuccess(false);
            return result;
        }

    }      
5、前端代碼
      
<div class="form-group">
                                <%--<label for="password">請輸入驗證碼--%>
                                </label>
                                <input id="code" type="text" class="form-control" name="code" width="400px" placeholder="請輸入驗證碼">
                                <a href="javascript:getVerifiCode()">
                                    <img id="yzm_img" style="cursor:pointer;width: 100px;height: 40px;margin: 0px 0 0 5px;
                                    border-radius: 3px;"
                                         title="點選重新整理驗證碼" src="/login/getVerifiCode" />
                                </a>
                            </div>      
function pageData() {
        var code=$("#code").val();
        var userName=$("#userName").val();
        var password=$("#password").val();
        var aa = $("input[type='checkbox']").is(":checked");//擷取選中狀态
        if(userName == ''){
            alert("請輸入使用者名。");
            return;
        }
        if(password == ''){
            alert("請輸入密碼。");
            return;
        }
        if(aa==true){
            setCookie();   //調用設定Cookie的方法
        }else if(aa==false){
            setCookie();  //調用設定Cookie的方法
        }

        var params = {
            userName:userName,
            password:password,
            code:code
        };
        var url = '/login/pageData';
        jQuery.ajax({
            type: 'POST',
            contentType: 'application/x-www-form-urlencoded',
            url: url,
            data: params,
            dataType: 'json',
            success: function (data) {
                // alert("成功啦");
                var code=data.code;
                if (code=="0000"){
                    alert("登陸成功!")
                    location.href="/tick/list";
                } else if(code=="0001"){
                    alert("登陸提示:"+data.msg);
                }else if(code=="0002"){
                    alert("登陸提示:"+data.msg);
                }else if(code=="0005"){
                    alert("登陸提示:"+data.msg);
                }else {
                    alert("未知異常!");
                }

            },
            error: function (data) {
                alert("失敗啦");
            }
        });
    }      
JAVA實作圖檔驗證
JAVA實作圖檔驗證
好了,這就是基本上實作的步驟,最後再上幾張實作效果圖↑↑↑↑↑      
@注:本部落格僅為個人學習筆記。 所屬人:Yuan