flask7 圖形驗證碼

app

from flask import Flask
from flask_script import Manager
from App.views import bp

app = Flask(__name__)
app.config.from_pyfile("settings.py")
manager = Manager(app)
# 註冊藍圖
app.register_blueprint(bp)

if __name__ == '__main__':
    manager.run()

settings

from datetime import timedelta

# # 簽名加密,session使用
SECRET_KEY = "i9490kl*(780990HGjhsoid7872378287mn,,.,ghghY!@3"
# # session存活時間
PERMANENT_SESSION_LIFETIME = timedelta(days=3)
# # session是否持久存儲
PERMANENT = True

App.views

from flask import Blueprint,session, make_response,request,render_template,redirect

from App.forms import RegisterForm
from App.verifycode import  vc

bp = Blueprint("bp",__name__)

@bp.route("/verify/")
def verify_code():
    result = vc.generate()
    # 把驗證碼字符串保存到session
    session['code'] = vc.code
    # 創建響應對象
    response = make_response(result)
    response.headers["Content-Type"] = "image/png"
    return response

# 用戶註冊
@bp.route("/register/",methods=['GET','POST'])
def register_user():
    form = RegisterForm()
    if request.method == 'POST':
        if form.validate_on_submit():
            print(form)
            return redirect('/verify')
    return render_template("register.html",**locals())

App.verifycode

import os
from io import BytesIO
from random import randint

from PIL import Image,ImageFont,ImageDraw

class VerifyCode:
    def __init__(self,width=100,height=40,size=4):
        """
        :param width: 驗證碼圖片寬度
        :param height: 高度
        :param size: 字符數
        """
        self.width = width
        self.height = height
        self.size = size
        self.__code = '' # 驗證碼字符串
        self.pen = None  # 畫筆
    @property
    def code(self):
        return self.__code

    def generate(self):
        # 1)、創建畫布
        im = Image.new("RGB",(self.width,self.height),self.__rand_color(150))
        self.pen = ImageDraw.Draw(im)
        # 2)、生成驗證碼字符串
        self.rand_string()
        # 3)、畫驗證碼
        self.__draw_code()
        # 4)、畫干擾點
        self.__draw_point()
        # 5)、畫干擾線
        self.__rand_line()
        # 6)、返回驗證碼圖片
        # 緩衝區
        buf = BytesIO()
        # 把圖片放到緩衝區
        im.save(buf,'png')
        # 獲取圖片的二進制
        res = buf.getvalue()
        buf.close()
        return res
        # im.save("vc.png")

    def __rand_color(self,min=0,max=255):
        return randint(min,max),randint(min,max),randint(min,max)

    # 驗證碼字符串
    def rand_string(self):
        self.__code = ''
        for i in range(self.size):
            self.__code += str(randint(0,9))

    #畫驗證碼
    def __draw_code(self):
        # 加載字體
        path = os.path.join(os.getcwd(),'static/fonts/SIMLI.TTF')
        print(path)
        font1 = ImageFont.truetype(path,size=20,encoding="utf-8")

        # 計算字符寬度
        width = (self.width-20) // self.size

        # 逐個字符畫
        for i in range(len(self.__code)):
            x = 13 + width * i  # 計算每個字符的x座標
            self.pen.text((x,9),self.__code[i],font=font1,fill=self.__rand_color(0,80))

    # 畫點
    def __draw_point(self):
        for i in range(100):
            self.pen.point((randint(1, self.width-1), randint(1, self.height-1)), self.__rand_color(30,100))

    def __rand_line(self):
        for i in range(5):
            self.pen.line([(randint(1, self.width-1), randint(1, self.height-1)), (randint(1, self.width-1), randint(1, self.height-1))], fill=self.__rand_color(50,150), width=2)


#單例屬性
vc = VerifyCode()

App.forms

from flask import session
from flask_wtf import FlaskForm
from wtforms import StringField
from wtforms.validators import ValidationError


class RegisterForm(FlaskForm):
    code = StringField()
    def validate_code(self,field):
        print(field.data ,session.get('code'))
        if field.data != session.get('code'):
            raise ValidationError("驗證碼匹配失敗")

register.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form action="{{ url_for('bp.register_user') }}" method="post">
    {{ form.csrf_token }}
    <input type="text" name="code">
    <img src="{{ url_for('bp.verify_code') }}" alt="" onclick="this.src={{ url_for('bp.verify_code') }}+'?'+Math.random()">
     {% for error in form.code.errors %}
        <span>{{ error }}</span>
    {% endfor %}
    <br>
    <input type="submit">
</form>
</body>
</html>
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章