更改验证码,简化目录
This commit is contained in:
@@ -14,7 +14,7 @@ MYSQL_HOST=127.0.0.1
|
|||||||
MYSQL_PORT=3306
|
MYSQL_PORT=3306
|
||||||
MYSQL_DATABASE=PearAdminFlask
|
MYSQL_DATABASE=PearAdminFlask
|
||||||
MYSQL_USERNAME=root
|
MYSQL_USERNAME=root
|
||||||
MYSQL_PASSWORD=123456
|
MYSQL_PASSWORD=root
|
||||||
|
|
||||||
# Redis 配置
|
# Redis 配置
|
||||||
# REDIS_HOST=127.0.0.1
|
# REDIS_HOST=127.0.0.1
|
||||||
|
|||||||
+1
-1
@@ -19,7 +19,7 @@ COPY . /app
|
|||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
RUN pip --no-cache-dir install -i ${PIPURL} --upgrade pip \
|
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 \
|
&& pip --no-cache-dir install -i ${PIPURL} gunicorn \
|
||||||
&& chmod +x start.sh
|
&& chmod +x start.sh
|
||||||
CMD ./start.sh
|
CMD ./start.sh
|
||||||
@@ -96,7 +96,7 @@ Pear Admin Flask
|
|||||||
git clone https://gitee.com/pear-admin/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
|
.env
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ from io import BytesIO
|
|||||||
from flask import session, make_response, current_app
|
from flask import session, make_response, current_app
|
||||||
from flask_login import current_user
|
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
|
from applications.schemas import PowerOutSchema
|
||||||
|
|
||||||
|
|
||||||
@@ -36,7 +36,7 @@ def make_menu_tree():
|
|||||||
if p.enable == 0:
|
if p.enable == 0:
|
||||||
continue
|
continue
|
||||||
# 一二级菜单
|
# 一二级菜单
|
||||||
if int(p.type) in [0,1] and p not in powers:
|
if int(p.type) in [0, 1] and p not in powers:
|
||||||
powers.append(p)
|
powers.append(p)
|
||||||
|
|
||||||
power_schema = PowerOutSchema(many=True) # 用已继承 ma.ModelSchema 类的自定制类生成序列化类
|
power_schema = PowerOutSchema(many=True) # 用已继承 ma.ModelSchema 类的自定制类生成序列化类
|
||||||
@@ -61,7 +61,8 @@ def make_menu_tree():
|
|||||||
|
|
||||||
# 生成验证码
|
# 生成验证码
|
||||||
def get_captcha():
|
def get_captcha():
|
||||||
code, image = gen_captcha()
|
image, code = vieCode().GetCodeImage()
|
||||||
|
code = ''.join(code).lower()
|
||||||
out = BytesIO()
|
out = BytesIO()
|
||||||
session["code"] = code
|
session["code"] = code
|
||||||
image.save(out, 'png')
|
image.save(out, 'png')
|
||||||
|
|||||||
@@ -55,6 +55,6 @@ def init_db():
|
|||||||
return
|
return
|
||||||
if init_database():
|
if init_database():
|
||||||
print('数据库%s创建成功' % str(DATABASE))
|
print('数据库%s创建成功' % str(DATABASE))
|
||||||
execute_fromfile('test/pear.sql')
|
execute_fromfile('pear.sql')
|
||||||
print('表创建成功')
|
print('表创建成功')
|
||||||
print('欢迎使用pear-admin-flask,请使用 flask run 命令启动程序')
|
print('欢迎使用pear-admin-flask,请使用 flask run 命令启动程序')
|
||||||
|
|||||||
Binary file not shown.
@@ -1,14 +1,121 @@
|
|||||||
from captcha.image import ImageCaptcha
|
import random, math
|
||||||
|
from PIL import Image, ImageDraw, ImageFont, ImageFilter
|
||||||
from PIL import Image
|
|
||||||
from random import choices
|
|
||||||
|
|
||||||
|
|
||||||
def gen_captcha(content='2345689abcdefghijklmnpqrstuvwxyzABCDEFGHIJKLMNPQRSTUVWXYZ'):
|
class vieCode:
|
||||||
""" 生成验证码 """
|
__fontSize = 20 # 字体大小
|
||||||
image = ImageCaptcha()
|
__width = 120 # 画布宽度
|
||||||
# 获取字符串
|
__heigth = 45 # 画布高度
|
||||||
captcha_text = "".join(choices(content, k=4)).lower()
|
__length = 4 # 验证码长度
|
||||||
# 生成图像
|
__draw = None # 画布
|
||||||
captcha_image = Image.open(image.generate(captcha_text))
|
__img = None # 图片资源
|
||||||
return captcha_text, captcha_image
|
__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_sqlalchemy import db, ma, init_databases
|
||||||
from .init_login import init_login_manager
|
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_template_directives import init_template_directives
|
||||||
from .init_error_views import init_error_views
|
from .init_error_views import init_error_views
|
||||||
from .init_mail import init_mail
|
from .init_mail import init_mail
|
||||||
@@ -12,7 +11,6 @@ from .init_dotenv import init_dotenv
|
|||||||
|
|
||||||
|
|
||||||
def init_plugs(app: Flask) -> None:
|
def init_plugs(app: Flask) -> None:
|
||||||
# init_debug_tool(app)
|
|
||||||
init_login_manager(app)
|
init_login_manager(app)
|
||||||
init_databases(app)
|
init_databases(app)
|
||||||
init_template_directives(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