圖片驗證碼功能實現

自定義圖片驗證類django

import os
import time
import random

from PIL import Image, ImageDraw, ImageFont


class Captcha(object):
    def __init__(self, request):
        """
        初始化,設置各類屬性
        """
        self.django_request = request
        self.session_key = "_django_captcha_key"
        self.captcha_expires_time = "_django_captcha_expires_time"

        # 驗證碼圖片尺寸
        self.img_width = 90
        self.img_height = 30

    def _get_font_size(self, code):
        """
        將圖片高度的80%做爲字體大小
        """
        s1 = int(self.img_height * 0.8)
        s2 = int(self.img_width / len(code))
        return int(min((s1, s2)) + max((s1, s2)) * 0.05)

    def _set_answer(self, answer):
        """
        設置答案和過時時間
        """
        self.django_request.session[self.session_key] = str(answer)
        self.django_request.session[self.captcha_expires_time] = time.time() + 60

    def _make_code(self):
        """
        生成隨機數或隨機字符串
        """
        string = random.sample("abcdefghkmnpqrstuvwxyzABCDEFGHGKMNOPQRSTUVWXYZ23456789", 4)
        self._set_answer("".join(string))
        return string

    def get(self):
        """
        生成驗證碼圖片,返回值爲圖片的bytes
        """
        background = (random.randrange(200, 255), random.randrange(200, 255), random.randrange(200, 255))
        code_color = (random.randrange(0, 50), random.randrange(0, 50), random.randrange(0, 50), 255)

        font_path = os.path.join(os.path.normpath(os.path.dirname(__file__)), "timesbi.ttf")

        image = Image.new("RGB", (self.img_width, self.img_height), background)
        code = self._make_code()
        font_size = self._get_font_size(code)
        draw = ImageDraw.Draw(image)

        # x是第一個字母的x座標
        x = random.randrange(int(font_size * 0.3), int(font_size * 0.5))

        for i in code:
            # 字符y座標
            y = random.randrange(1, 7)
            # 隨機字符大小
            font = ImageFont.truetype(font_path.replace("\\", "/"), font_size + random.randrange(-3, 7))
            draw.text((x, y), i, font=font, fill=code_color)
            # 隨機化字符之間的距離 字符粘連能夠下降識別率
            x += font_size * random.randrange(6, 8) / 10

        self.django_request.session[self.session_key] = "".join(code)
        return image

    def check(self, code):
        """
        檢查用戶輸入的驗證碼是否正確
        """
        _code = self.django_request.session.get(self.session_key) or ""
        if not _code:
            return False
        expires_time = self.django_request.session.get(self.captcha_expires_time) or 0
        # 注意 若是驗證以後不清除以前的驗證碼的話 可能會形成重複驗證的現象
        del self.django_request.session[self.session_key]
        del self.django_request.session[self.captcha_expires_time]
        if _code.lower() == str(code).lower() and time.time() < expires_time:
            return True
        else:
            return False

使用json

def img2base64(img):
    with BytesIO() as buf:
        img.save(buf, "gif")
        buf_str = buf.getvalue()
    img_prefix = "data:image/png;base64,"
    b64_str = img_prefix + b64encode(buf_str).decode("utf-8")
    return b64_str
HttpResponse(json.dumps(img2base64(Captcha(request).get())))
相關文章
相關標籤/搜索