圖形驗證碼及驗證碼的動態刷新


下列代碼都是以自己的項目實例講述的,相關的文本內容很少,主要說明全在代碼注釋中

自制圖形驗證碼  

  這里所說的圖形驗證碼都是自制的圖形,通過畫布、畫筆、畫筆字體的顏色繪制而成的。將驗證碼封裝成一個類比較好管理,代碼里有絕對詳細的注釋,當然大家可以直接復制。

里面涉及的字體都是從系統電腦上自帶的,大家直接復制當前目錄下就可以了。

主目錄/utils/captcha/__init__.py

import random
import string

# Image:一個畫布
# ImageDraw:一個畫筆
# ImageFont:畫筆的字體
from PIL import Image, ImageDraw, ImageFont


# Captcha驗證碼
class Captcha(object):
    # 生成4位數的驗證碼
    numbers = 4
    # 驗證碼圖片的寬度和高度
    size = (100, 30)
    # 驗證碼字體大小
    fontsize = 25
    # 加入干擾線的條數
    line_number = 2

    # 構建一個驗證碼源文本
    SOURCE = list(string.ascii_letters)
    for index in range(0, 10):
        SOURCE.append(str(index))

    # 用來繪制干擾線
    @classmethod
    def __gene_line(cls, draw, width, height):
        begin = (random.randint(0, width), random.randint(0, height))
        end = (random.randint(0, width), random.randint(0, height))
        draw.line([begin, end], fill=cls.__gene_random_color(), width=2)

    # 用來繪制干擾點
    @classmethod
    def __gene_points(cls, draw, point_chance, width, height):
        # 大小限在【0, 100】中
        chance = min(100, max(0, int(point_chance)))
        for w in range(width):
            for h in range(height):
                tmp = random.randint(0, 100)
                if tmp > 100 - chance:
                    draw.point((w, h), fill=cls.__gene_random_color())

    # 生成隨機顏色
    @classmethod
    def __gene_random_color(cls, start=0, end=255):
        random.seed()
        return (random.randint(start, end),
                random.randint(start, end),
                random.randint(start, end))

    # 隨機選擇一個字體
    @classmethod
    def __gene_random_font(cls):
        fonts = [
            "PAPYRUS.TTF",
            "CENTAUR.TTF",
            "Inkfree.ttf",
            "verdana.ttf",
        ]
        font = random.choice(fonts)
        return "utils/captcha/"+font

    # 用來隨機生成一個字符串(包括英文和數字)
    @classmethod
    def gene_text(cls, numbers):
        # numbers是生成驗證碼的位數
        return " ".join(random.sample(cls.SOURCE, numbers))

    # 生成驗證碼
    @classmethod
    def gene_graph_captcha(cls):
        # 驗證碼圖片的寬高
        width, height = cls.size
        # 創建圖片
        image = Image.new("RGBA", (width, height), cls.__gene_random_color(0, 100))
        # 驗證碼的字體
        font = ImageFont.truetype(cls.__gene_random_font(), cls.fontsize)
        # 創建畫筆
        draw = ImageDraw.Draw(image)
        # 生成字符串
        text = cls.gene_text(cls.numbers)
        # 獲取字體的尺寸
        font_width, font_height = font.getsize(text)
        # 填充字符串
        draw.text(((width-font_width)/2, (height-font_height)/2),
                  text, font=font, fill=cls.__gene_random_color(150, 255))
        # 繪制干擾線
        for x in range(0, cls.line_number):
            cls.__gene_line(draw, width, height)
        # 繪制干擾點
        cls.__gene_points(draw, 10, width, height)
        with open("captcha.png", "wb") as fp:
            image.save(fp)
        return text, image

顯示圖形驗證碼

  一般圖形驗證碼都是在表單中,這樣短時間內的數據及建議保存在redis緩存中(用戶點擊動態刷新圖形驗證碼)。首先我們繪制圖形驗證碼保存到項目的目錄下(入口文件是主目錄(項目目錄)app.py文件,圖片也保存到主目錄下),然后通過url地址訪問自制的圖形驗證碼(這里我只添加主要的代碼)

主目錄/common/views.py

@bp.route("/captcha")
def graph_captcha():
    """
    使用定義好的圖形驗證碼類,來制作驗證碼
    以驗證碼為鍵、驗證碼為值(為了用戶的體驗,讓其忽略大小寫)存儲在redis緩存中
    通過BytesIO字節流的方式保存和訪問圖片
    :return: 圖片響應
    """
    # 獲取驗證碼
    text, image = Captcha.gene_graph_captcha()
    cpcache.set(text.lower(), text.lower())

    # BytesIO:字節流
    out = BytesIO()
    # 保存圖片
    image.save(out, "png")
    # 存儲完圖片,將文件的指針指向文件頭,使下次保存圖片能覆蓋前面保存的圖片,節省空間
    out.seek(0)
    # 訪問圖片,並將其作為一個響應返回給前台
    resp = make_response(out.read())
    resp.content_type = "image/png"
    return resp

前端頁面的代碼如下:

<div class="form-group">
    <div class="input-group">
        <input type="text" class="form-control" name="graph_captcha" placeholder="圖形驗證碼">
        <span class="input-group-addon captcha-addon">
            <img id="captcha-img" class="captcha-img" src="{{ url_for("common.graph_captcha") }}" alt="">
        </span>
    </div>
</div>

動態刷新驗證碼

  無非就是再生成一張圖形驗證碼,通過url再次訪問就可以,但是這樣做是非常麻煩的,這里我很難解釋(很難!!!),大家就直接復制代碼吧,這個代碼就是點擊圖片生成一個新的url訪問圖片

這個文件放在公共的目錄下就可以了

var cpparam = {
    setParam: function(href, key, value){
        //重新加載整個頁面
        var isReplaced = false;
        var urlArray = href.split("?");
        if(urlArray.length > 1){
            var queryArray = urlArray[1].split("&");
            for(var i=0; i < queryArray.length; i++){
                var paramArray = queryArray[i].split("=");
                if(paramArray[0] == key){
                    paramArray[1] = value;
                    queryArray[i] = paramArray.join("=");
                    isReplaced = true;
                    break;
                }
            }
            if(!isReplaced){
                var params = {};
                params[key] = value;
                if(urlArray.length > 1){
                    href = href + "$" + $.param(params);
                }else{
                    href = href + "?" + $.param(params);
                }
            }else{
                var params = queryArray.join("&");
                urlArray[1] = params;
                href = urlArray.join("?");
            }
        }else{
            var param = {};
            param[key] = value;
            if(urlArray.length > 1){
                href = href + "$" + $.param(param);
            }else{
                href = href + "?" + $.param(param);
            }
        }
        return href;
    }
};

  對應html的js文件就需要實現元素(圖片)點擊刷新圖片,調用上面的變量cpparam生成一章圖片並訪問。

$(function(){
   $("#captcha-img").on("click", function(){
       var self = $(this);
       var src = self.attr("src");
       var newsrc = cpparam.setParam(src, "xx", Math.random());
       self.attr("src", newsrc);
   });
});

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM