1. 程式人生 > >java生成圖片驗證碼(字母 | 運算 | 漢字)

java生成圖片驗證碼(字母 | 運算 | 漢字)

java生成圖片驗證碼(字母|運算|漢字)

先看下以下效果圖,ui請勿參考。。

1.首先看運算的,左邊正確輸入,右邊錯誤輸入,驗證碼超時時間是1分,下面超時示例

字母驗證碼和漢字

2.後臺工具類程式碼

package com.ljm.verification.util;


import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.util.Random;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

/**
 * @author lijunming
 * @date 2018/10/26 2:57 PM
 */
public class RandomValidateCode {
    private static int width = 135;// 圖片寬
    private static int height = 28;// 圖片高
    private static int lineSize = 40;// 干擾線數量
    private static Random random = new Random();

    /**
     * 設定驗證碼字型
     *
     * @return 字型
     */
    private static Font getFont() {
        return new Font("Fixedsys", Font.CENTER_BASELINE, 18);
    }

    /**
     * 設定驗證碼顏色
     *
     * @param fc
     * @param bc
     * @return rgb值
     */
    private static Color getRandColor(int fc, int bc) {
        if (fc > 255)
            fc = 255;
        if (bc > 255)
            bc = 255;
        int r = fc + random.nextInt(bc - fc - 16);
        int g = fc + random.nextInt(bc - fc - 14);
        int b = fc + random.nextInt(bc - fc - 18);
        return new Color(r, g, b);
    }

    /**
     * 生成隨機驗證碼,繪製成圖片,並且寫入結果
     *
     * @param request
     * @param response
     */
    public static void getRandcode(HttpServletRequest request,
                                   HttpServletResponse response) {
        HttpSession session = request.getSession();
        // BufferedImage類是具有緩衝區的Image類,Image類是用於描述影象資訊的類
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_BGR);
        Graphics g = image.getGraphics();// 產生Image物件的Graphics物件,改物件可以在影象上進行各種繪製操作
        g.fillRect(0, 0, width, height);
        g.setFont(new Font("Times New Roman", Font.ROMAN_BASELINE, 45)); //圖片上字的大小
        g.setColor(getRandColor(110, 133));
        // 繪製干擾線
        for (int i = 0; i <= lineSize; i++) {
            drowLine(g);
        }
        // 繪製隨機驗證嗎
        String randomString = getValidate();
        //獲得生成的驗證碼,然後跟使用者輸入的進行比較
        session.setAttribute("verification", result);
        session.setMaxInactiveInterval(30);
        String[] arr = randomString.toString().split("");
        for (int i = 1; i <= arr.length; i++) {
            drowString(g, arr[i - 1], i);
        }
        g.dispose();
        try {
            // 將記憶體中的圖片通過流動形式輸出到客戶端
            ImageIO.write(image, "JPEG", response.getOutputStream());
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    /**
     * 繪製圖片
     */
    private static String drowString(Graphics g, String randomString, int i) {
        int j = 15;
        if (result instanceof Integer) {
            j = 11;
        }
        g.setFont(getFont());
        g.setColor(new Color(random.nextInt(101), random.nextInt(111), random
                .nextInt(121)));
        g.translate(random.nextInt(3), random.nextInt(3));
        g.translate(random.nextInt(3), random.nextInt(3));
        g.drawString(randomString, j * i, 12);
        return randomString;
    }

    /**
     * 繪製干擾線
     */
    private static void drowLine(Graphics g) {
        int x = random.nextInt(width);
        int y = random.nextInt(height);
        int xl = random.nextInt(13);
        int yl = random.nextInt(15);
        g.drawLine(x, y, x + xl, y + yl);
    }

    public static Object result;

    /**
     * 生成字母驗證碼
     * @return 驗證碼的內容
     */
    public static String createAB() {
        String[] abc = new String[]{"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "q", "r", "s", "t", "u", "v", "o", "p", "w", "x", "z", "y", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "Q", "R", "S", "T", "U", "V", "O", "P", "W", "X", "Y", "Z"};
        Random rd = new Random();
        int index = rd.nextInt(abc.length);
        String one = abc[index];
        index = rd.nextInt(abc.length);
        String two = abc[index];
        index = rd.nextInt(abc.length);
        String three = abc[index];
        index = rd.nextInt(abc.length);
        String four = abc[index];
        result = one + two + three + four;
        String str = one + two + three + four;
        return str;
    }

    /**
     * 生成加減乘除演算法驗證碼
     * 由於2位數的 乘除對某些人算起來麻煩
     * 有興趣的可以擴充套件乘法和除法
     * @return 驗證碼的內容
     */
    public static String createNumber() {
        String fu[] = new String[]{"+", "-", "*", "/"};
        Random rd = new Random();
        int i = rd.nextInt(2);
        int num1 = rd.nextInt(100);
        int num2 = rd.nextInt(100);
        if (i == 0) {
            result = num1 + num2;
        } else {
            //迴圈保證永遠不會出現減法結果是負數
            while (num1 < num2) {
                num1 = rd.nextInt(100);
            }
            result = num1 - num2;
        }
        String str = num1 + fu[i] + num2 + "=";
        return str;
    }

    /**
     * 生產漢字驗證嗎
     * @return 驗證碼的內容
     */
    public static String createChinese() {
        String chinese[] = new String[]{
                "勿", "忘", "初", "心", "方", "得", "始", "終", "認", "真", "切", "慫", "從", "一", "而", "終", "英", "雄", "聯", "盟"
        };
        Random rd = new Random();
        int index = rd.nextInt(chinese.length);
        String one = chinese[index];
        index = rd.nextInt(chinese.length);
        String two = chinese[index];
        index = rd.nextInt(chinese.length);
        String three = chinese[index];
        index = rd.nextInt(chinese.length);
        String four = chinese[index];
        result = one + two + three + four;
        String str = one + two + three + four;
        return str;
    }

    /**
     * 隨機呼叫驗證碼
     */
    public static String getValidate() {
        Random rd = new Random();
        int i = rd.nextInt(4);
        if (i == 1) {
            return createAB();
        } else if (i == 2) {
            return createChinese();
        }
        return createNumber();
    }
}

3.Controller

package com.ljm.verification.controller;

import com.ljm.verification.util.RandomValidateCode;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

/**
 * @author lijunming
 * @date 2018/10/26 3:57 PM
 */
@Controller
public class TestController {

    /*
     * 去登陸頁面
     */
    @GetMapping("/login")
    public String toLogin(){
        return "login";
    }

    /*
     * 登入頁面生成驗證碼
     */
    @RequestMapping(value = "/getVerify.htm")
    public void getVerify(HttpServletRequest request, HttpServletResponse response){
        response.setContentType("image/jpeg");//設定相應型別,告訴瀏覽器輸出的內容為圖片
        response.setHeader("Pragma", "No-cache");//設定響應頭資訊,告訴瀏覽器不要快取此內容
        response.setHeader("Cache-Control", "no-cache");
        response.setDateHeader("Expire", 0);
        try {
            RandomValidateCode.getRandcode(request, response);//輸出驗證碼圖片方法
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /*
     * 驗證輸入的驗證碼是否正確
     */
    @RequestMapping("/checkValidate")
    @ResponseBody
    public String checkValidate(@RequestParam("verification")Object yzm, HttpSession session) throws Exception{
        Object result=session.getAttribute("verification");
        //驗證碼只有半分鐘的有效期,超時返回-1
        if(session.getAttribute("verification")==null){
            return "-1";
        }
        //如果為字母驗證碼或者    1表示通告,0表示驗證失敗
        if(result instanceof String){
            if(yzm.toString().toUpperCase().equals(result.toString().toUpperCase())){
                return "1";
            }
            return "0";
            //如果為數字驗證碼
        }else{
            if(result.toString().equals(yzm)){
                return "1";
            }
        }
        return "0";
    }
}

4.前臺頁面

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style type="text/css">
         div{
             text-align: center;
         }
        form{
            margin-top:10%;
        }
    </style>
</head>
<body>
<div >
    <form  action="login"method="post">
        <div id="error"></div>
        賬號:<input type="text" name="userName"/><br/>
        密碼:<input type="password" name="password" /><br/>
        <img id="yzm" src="getVerify.htm"/> <a href="javascript:replace()">換一張</a><br/>
        驗證碼<input type="text" name="yzm"/>
        <input type="button" value="登陸" id="login"/>
    </form>
</div>
</body>
<script type="text/javascript" src="jquery-1.8.0.js"></script>
<script type="text/javascript">
    function replace(){
        $("#yzm").attr("src","getVerify.htm?t="+ Math.random());
    }
    $(function(){
        $("#login").click(function(){
            var flags=false;
            var verification=$("[name='yzm']").val();
            $.ajax({
                url:"checkValidate",
                async:false,
                type:"get",
                data:{"verification":verification},
                dataType:"text",
                success:function(flag){
                    if(flag=="-1"){
                        $("#error").html("驗證碼已超時,請換個","red");
                        flags=true;
                    }else if (flag=="0"){
                        $("#error").html("驗證碼錯誤").css("color","red");
                        flags=true;
                    }else{
                        $("#error").html("登陸成功").css("color","green");
                    }
                }
            });
            //如果驗證失敗則不進後面的登陸
            if(flags){
                return;
            }
        });
    })
</script>
</html>

5.完整專案程式碼,由於小專案,沒有用github