更改验证码,简化目录
This commit is contained in:
@@ -14,7 +14,7 @@ MYSQL_HOST=127.0.0.1
|
||||
MYSQL_PORT=3306
|
||||
MYSQL_DATABASE=PearAdminFlask
|
||||
MYSQL_USERNAME=root
|
||||
MYSQL_PASSWORD=123456
|
||||
MYSQL_PASSWORD=root
|
||||
|
||||
# Redis 配置
|
||||
# REDIS_HOST=127.0.0.1
|
||||
|
||||
+1
-1
@@ -19,7 +19,7 @@ COPY . /app
|
||||
WORKDIR /app
|
||||
|
||||
RUN pip --no-cache-dir install -i ${PIPURL} --upgrade pip \
|
||||
&& pip --no-cache-dir install -i ${PIPURL} -r requirement/requirement-dev.txt \
|
||||
&& pip --no-cache-dir install -i ${PIPURL} -r requirement/dev.txt \
|
||||
&& pip --no-cache-dir install -i ${PIPURL} gunicorn \
|
||||
&& chmod +x start.sh
|
||||
CMD ./start.sh
|
||||
@@ -96,7 +96,7 @@ Pear Admin Flask
|
||||
git clone https://gitee.com/pear-admin/pear-admin-flask
|
||||
|
||||
# 安 装
|
||||
pip install -r requirement\requirement-dev.txt
|
||||
pip install -r requirement\dev.txt
|
||||
|
||||
# 配 置
|
||||
.env
|
||||
|
||||
@@ -4,7 +4,7 @@ from io import BytesIO
|
||||
from flask import session, make_response, current_app
|
||||
from flask_login import current_user
|
||||
|
||||
from applications.common.utils.gen_captcha import gen_captcha
|
||||
from applications.common.utils.gen_captcha import vieCode
|
||||
from applications.schemas import PowerOutSchema
|
||||
|
||||
|
||||
@@ -61,7 +61,8 @@ def make_menu_tree():
|
||||
|
||||
# 生成验证码
|
||||
def get_captcha():
|
||||
code, image = gen_captcha()
|
||||
image, code = vieCode().GetCodeImage()
|
||||
code = ''.join(code).lower()
|
||||
out = BytesIO()
|
||||
session["code"] = code
|
||||
image.save(out, 'png')
|
||||
|
||||
@@ -55,6 +55,6 @@ def init_db():
|
||||
return
|
||||
if init_database():
|
||||
print('数据库%s创建成功' % str(DATABASE))
|
||||
execute_fromfile('test/pear.sql')
|
||||
execute_fromfile('pear.sql')
|
||||
print('表创建成功')
|
||||
print('欢迎使用pear-admin-flask,请使用 flask run 命令启动程序')
|
||||
|
||||
Binary file not shown.
@@ -1,14 +1,121 @@
|
||||
from captcha.image import ImageCaptcha
|
||||
|
||||
from PIL import Image
|
||||
from random import choices
|
||||
import random, math
|
||||
from PIL import Image, ImageDraw, ImageFont, ImageFilter
|
||||
|
||||
|
||||
def gen_captcha(content='2345689abcdefghijklmnpqrstuvwxyzABCDEFGHIJKLMNPQRSTUVWXYZ'):
|
||||
""" 生成验证码 """
|
||||
image = ImageCaptcha()
|
||||
# 获取字符串
|
||||
captcha_text = "".join(choices(content, k=4)).lower()
|
||||
# 生成图像
|
||||
captcha_image = Image.open(image.generate(captcha_text))
|
||||
return captcha_text, captcha_image
|
||||
class vieCode:
|
||||
__fontSize = 20 # 字体大小
|
||||
__width = 120 # 画布宽度
|
||||
__heigth = 45 # 画布高度
|
||||
__length = 4 # 验证码长度
|
||||
__draw = None # 画布
|
||||
__img = None # 图片资源
|
||||
__code = None # 验证码字符
|
||||
__str = None # 自定义验证码字符集
|
||||
__inCurve = True # 是否画干扰线
|
||||
__inNoise = True # 是否画干扰点
|
||||
__type = 2 # 验证码类型 1、纯字母 2、数字字母混合
|
||||
__fontPatn = 'applications/common/utils/fonts/1.ttf' # 字体
|
||||
|
||||
def GetCodeImage(self, size=80, length=4):
|
||||
'''获取验证码图片
|
||||
@param int size 验证码大小
|
||||
@param int length 验证码长度
|
||||
'''
|
||||
# 准备基础数据
|
||||
self.__length = length
|
||||
self.__fontSize = size
|
||||
self.__width = self.__fontSize * self.__length
|
||||
self.__heigth = int(self.__fontSize * 1.5)
|
||||
|
||||
# 生成验证码图片
|
||||
self.__createCode()
|
||||
self.__createImage()
|
||||
self.__createNoise()
|
||||
self.__printString()
|
||||
self.__cerateFilter()
|
||||
|
||||
return self.__img, self.__code
|
||||
|
||||
def __cerateFilter(self):
|
||||
'''模糊处理'''
|
||||
self.__img = self.__img.filter(ImageFilter.BLUR)
|
||||
filter = ImageFilter.ModeFilter(8)
|
||||
self.__img = self.__img.filter(filter)
|
||||
|
||||
def __createCode(self):
|
||||
'''创建验证码字符'''
|
||||
# 是否自定义字符集合
|
||||
if not self.__str:
|
||||
# 源文本
|
||||
number = "3456789"
|
||||
srcLetter = "qwertyuipasdfghjkzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM"
|
||||
srcUpper = srcLetter.upper()
|
||||
if self.__type == 1:
|
||||
self.__str = number
|
||||
else:
|
||||
self.__str = srcLetter + srcUpper + number
|
||||
|
||||
# 构造验证码
|
||||
self.__code = random.sample(self.__str, self.__length)
|
||||
|
||||
def __createImage(self):
|
||||
'''创建画布'''
|
||||
bgColor = (random.randint(200, 255), random.randint(200, 255), random.randint(200, 255))
|
||||
self.__img = Image.new('RGB', (self.__width, self.__heigth), bgColor)
|
||||
self.__draw = ImageDraw.Draw(self.__img)
|
||||
|
||||
def __createNoise(self):
|
||||
'''画干扰点'''
|
||||
if not self.__inNoise:
|
||||
return
|
||||
font = ImageFont.truetype(self.__fontPatn, int(self.__fontSize / 1.5))
|
||||
for i in range(5):
|
||||
# 杂点颜色
|
||||
noiseColor = (random.randint(150, 200), random.randint(150, 200), random.randint(150, 200))
|
||||
putStr = random.sample(self.__str, 2)
|
||||
for j in range(2):
|
||||
# 绘杂点
|
||||
size = (random.randint(-10, self.__width), random.randint(-10, self.__heigth))
|
||||
self.__draw.text(size, putStr[j], font=font, fill=noiseColor)
|
||||
pass
|
||||
|
||||
def __createCurve(self):
|
||||
'''画干扰线'''
|
||||
if not self.__inCurve:
|
||||
return
|
||||
x = y = 0
|
||||
|
||||
# 计算曲线系数
|
||||
a = random.uniform(1, self.__heigth / 2)
|
||||
b = random.uniform(-self.__width / 4, self.__heigth / 4)
|
||||
f = random.uniform(-self.__heigth / 4, self.__heigth / 4)
|
||||
t = random.uniform(self.__heigth, self.__width * 2)
|
||||
xend = random.randint(self.__width / 2, self.__width * 2)
|
||||
w = (2 * math.pi) / t
|
||||
|
||||
# 画曲线
|
||||
color = (random.randint(30, 150), random.randint(30, 150), random.randint(30, 150))
|
||||
for x in range(xend):
|
||||
if w != 0:
|
||||
for k in range(int(self.__heigth / 10)):
|
||||
y = a * math.sin(w * x + f) + b + self.__heigth / 2
|
||||
i = int(self.__fontSize / 5)
|
||||
while i > 0:
|
||||
px = x + i
|
||||
py = y + i + k
|
||||
self.__draw.point((px, py), color)
|
||||
i -= i
|
||||
|
||||
def __printString(self):
|
||||
'''打印验证码字符串'''
|
||||
font = ImageFont.truetype(self.__fontPatn, self.__fontSize)
|
||||
x = 0
|
||||
# 打印字符到画板
|
||||
for i in range(self.__length):
|
||||
# 设置字体随机颜色
|
||||
color = (random.randint(30, 150), random.randint(30, 150), random.randint(30, 150))
|
||||
# 计算座标
|
||||
x = random.uniform(self.__fontSize * i * 0.95, self.__fontSize * i * 1.1)
|
||||
y = self.__fontSize * random.uniform(0.3, 0.5)
|
||||
# 打印字符
|
||||
self.__draw.text((x, y), self.__code[i], font=font, fill=color)
|
||||
|
||||
@@ -2,7 +2,6 @@ from flask import Flask
|
||||
|
||||
from .init_sqlalchemy import db, ma, init_databases
|
||||
from .init_login import init_login_manager
|
||||
from .init_debug_tool import init_debug_tool
|
||||
from .init_template_directives import init_template_directives
|
||||
from .init_error_views import init_error_views
|
||||
from .init_mail import init_mail
|
||||
@@ -12,7 +11,6 @@ from .init_dotenv import init_dotenv
|
||||
|
||||
|
||||
def init_plugs(app: Flask) -> None:
|
||||
# init_debug_tool(app)
|
||||
init_login_manager(app)
|
||||
init_databases(app)
|
||||
init_template_directives(app)
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
from flask import Flask
|
||||
from flask_debugtoolbar import DebugToolbarExtension
|
||||
|
||||
|
||||
def init_debug_tool(app: Flask):
|
||||
toolbar = DebugToolbarExtension()
|
||||
toolbar.init_app(app)
|
||||
@@ -0,0 +1,15 @@
|
||||
Flask
|
||||
Flask-APScheduler
|
||||
Flask-Migrate
|
||||
Flask-Login
|
||||
Flask_Reuploaded
|
||||
Flask-SQLAlchemy
|
||||
flask-marshmallow
|
||||
marshmallow-sqlalchemy
|
||||
PyMySQL
|
||||
psutil
|
||||
Flask-Mail
|
||||
sqlparse
|
||||
Pillow
|
||||
python-dotenv
|
||||
webargs
|
||||
@@ -1,17 +0,0 @@
|
||||
Flask==2.1.1
|
||||
Flask-APScheduler==1.12.2
|
||||
Flask-DebugToolbar==0.11.0
|
||||
Flask-Migrate==3.1.0
|
||||
Flask-Login==0.6.0
|
||||
Flask_Reuploaded==0.5.0
|
||||
Flask-SQLAlchemy==2.5.1
|
||||
flask-marshmallow==0.14.0
|
||||
marshmallow-sqlalchemy==0.26.1
|
||||
PyMySQL==1.0.2
|
||||
psutil==5.8.0
|
||||
Flask-Mail==0.9.1
|
||||
sqlparse==0.4.2
|
||||
captcha==0.3
|
||||
Pillow==8.2.0
|
||||
python-dotenv==0.19.1
|
||||
webargs==8.0.1
|
||||
Reference in New Issue
Block a user