From 65e72ce08bf82defd5f532736b63b169dc5979b1 Mon Sep 17 00:00:00 2001 From: Corley Date: Fri, 5 Jun 2020 21:33:45 +0800 Subject: [PATCH] V1.3 --- README.md | 8 +++- __pycache__/bbs.cpython-37.pyc | Bin 646 -> 694 bytes __pycache__/config.cpython-37.pyc | Bin 599 -> 808 bytes __pycache__/exts.cpython-37.pyc | Bin 272 -> 325 bytes apps/cms/__pycache__/forms.cpython-37.pyc | Bin 1423 -> 2087 bytes apps/cms/__pycache__/models.cpython-37.pyc | Bin 1546 -> 2475 bytes apps/cms/__pycache__/views.cpython-37.pyc | Bin 3212 -> 4407 bytes apps/cms/forms.py | 17 ++++++- apps/cms/models.py | 45 +++++++++++++++++- apps/cms/views.py | 35 ++++++++++++-- bbs.py | 4 +- config.py | 16 ++++++- exts.py | 5 +- manage.py | 2 +- .../__pycache__/ba80d307aa21_.cpython-37.pyc | Bin 0 -> 1268 bytes migrations/versions/ba80d307aa21_.py | 43 +++++++++++++++++ requirements.txt | 1 + static/cms/css/cms_base.css | 4 ++ static/cms/js/resetemail.js | 26 +++++----- templates/cms/cms_resetemail.html | 6 +-- templates/cms/cms_resetpwd.html | 5 -- utils/__pycache__/clcache.cpython-37.pyc | Bin 0 -> 770 bytes .../__pycache__/random_captcha.cpython-37.pyc | Bin 0 -> 606 bytes utils/clcache.py | 18 +++++++ utils/random_captcha.py | 14 ++++++ 25 files changed, 213 insertions(+), 36 deletions(-) create mode 100644 migrations/versions/__pycache__/ba80d307aa21_.cpython-37.pyc create mode 100644 migrations/versions/ba80d307aa21_.py create mode 100644 utils/__pycache__/clcache.cpython-37.pyc create mode 100644 utils/__pycache__/random_captcha.cpython-37.pyc create mode 100644 utils/clcache.py create mode 100644 utils/random_captcha.py diff --git a/README.md b/README.md index 83c4787..2470c97 100644 --- a/README.md +++ b/README.md @@ -9,4 +9,10 @@ 在V1.0的基础上进一步实现CMS用户登录、错误信息返回、登录限制和CSRF保护、CMS用户名渲染和注销、CMS个人页面和模板抽离等功能,进一步丰富后台管理功能。 #### V1.2 -在V1.1的基础上实现后台修改密码布局、通过Ajax实现局部更新修改密码、优化Json数据返回、sweetalert美化提示框、修改邮箱界面搭建功能。 \ No newline at end of file +在V1.1的基础上实现后台修改密码布局、通过Ajax实现局部更新修改密码、优化Json数据返回、sweetalert美化提示框、修改邮箱界面搭建功能。 + +#### V1.3 +在V1.2的时候进一步完善,首先实现在Flask中发送邮件,并进一步定义发送验证码,并进一步实现修改邮箱,还对权限和角色模型进行了定义。 + +注意: +在配置文件config.md中需要将自己的邮箱信息输入,才能正常实现其功能。 \ No newline at end of file diff --git a/__pycache__/bbs.cpython-37.pyc b/__pycache__/bbs.cpython-37.pyc index 1565c985d70c85eefe392a043c03a64f20ee6cdd..c3e0c93d0a61e54f08b1452ad577153489dcbeb3 100644 GIT binary patch delta 340 zcmX}ny-ve05CGs_nja@|LLmZ)g@FZS>A(vhK(K)jFnJ(KY6q1jZE#Y`#!v~dbcpf- zL1N$u5RZYxM0go48L)J|&u8CBe%3xT=g4ua9eW4L kfl3I?A30IT9s6#xJL delta 325 zcmdnS+Q!Q3#LLUY00d@jhvL>x~_kkP#@y4&tS7*f6BBEZ|M$28pF|FW^gMgR?lmEUpyJY^I_fplbdU z_7tvOkY2Wl7aZ%EQj#sOf4@iVgU&XBo+t&MZq>g#aSnBVf1Aa1j-f(PG)E7m6HN8 WS(tbjA&`Ta1IXfHGO4naC%>m@!e^&?bdFiX)XhiZg{HiYtXPiaUiXiYJv} z0dETTLdGb*6rL#l6y7KSpen%>z9^v-{wQG}Et0|*%%CYSu_D?l#4S^Tk%8f*2+-)4 z{6M0LyEwO`K(DY+FF8Lq)0+t>B4}i3WMFJzX>4KP01=N8NKC2B$Vp90OHV9JOG!yd z)D)fg)JZH#B*fJ>z{fGfHQq5a#6LdB)yLn_WwJVBZPG1nUq?@$_+ZzdFxQ}4oM29X ze^AIR9xyXB*fl=HC-@dGj2GnR=<5pQ1~>)>hx-S)+!6-My12SIhWdm6&GK_`4O+=i iBn)(Sk?`cTj1w4DCfhMd@H4V7b1}0pu>ffx$pip2KvjbP delta 112 zcmZ3%cAbUKiIR-Hgkc$SYZ|0pz4Gq%h_%ey2S$GuH;}SVgrg4u}!S$;{vgG7$SWBp2IQnLq%h_%QJ18M}sCQbkAUhXEM`^u~?*6+z!uT7D%@w zu5xWj;+g}C3X3Dxxq;kp;>Z)oO&&uYi+B=w2e*)0E#ArFW0IX{QdG9O5)7on&igsH zz;mTSacV?}qFDK6TQ-D7-p%Lo6VA%-_mB=MunInrmn*o!3~I_L`>3sZ&?=7NlaC3#kO9#X{8DE1 z6Q~fq!I*m1OyQ>uA{$iI3)Q0zG|?c`i!Ps@;i8`$V+hQca%NC-@yJV^Mhm*#?#UTC znRI!Sy@#T@hT;z+I1&S1m6+@(j>>_{H5do3)PQNI(Xo73K-4O`TBB7!W^xlN6AP2~ z9N#I8P)2SRg;yTLJsS(3w%;x_7uL7ezc%WdTbs*`cQ1A}HvVqD+}Zfvd|qq3{<8Bk z*n0K>6F_;WQX+6|st9GuIoh=>F8%pYYko$*`R)3Ao@zyphC)@jf#P35s7RC2B+SXU z%D5^erLI<#HJDQ?su-%sb!|(ScC=O65c@`Emx`5t$6p&YOcP)kZl7y zD>q%rPvk-syDlgC&{WWvFl*c?J#7Ef+~SNQ1O;Ymq7#=;eS`@SXULwMSVB0w;I};v z)UT^b=BX#G#&+5kCsFH10|_R+9ncN4{fE;%^uN!j9TP`2Q`Egt=+suNpw81*)W3uK zT^!BE0REwR?6y%CWMo0QQ9Bi+wQM!IChM9h(GC4}5JlndPl<@mp^go;a;f0@QO=^N n6Eq)DTSl86NJJC{MG%_9UXhnw=PDrcX_&H*g}9Q^@df=Kw3ZR> delta 530 zcmZutF-yZh6wb>fmrHBgSlgP4-9(6kf}0=?4%MZCcDq3=UX()4%B5OxanQZg6Gt8W z3xb0#4o>db9sC!*D=tC~-p73(-@Wg>dk)6M@^-0Iu<$%Rd>wYkq#Rx!ArqE>#FD^4 z+T50e6EK>cIMU^=q?}5Rdy;Vm){Z5JaBeN(#Bf8nkK7d$IgNef1>~M!$k~(^h2OQJ z!jB1!NanN$N@m6GQ1#DF+xvL*9cTYzdCEjd4V1pGCD}a`ADdidB_mBcNULOS5)2>ei>oZ$p;QaTUGG8GUpNr9wOY~cgN+1R8=9C1%XXa-3L-5P`&iybf z7`VQ?ryu|68OGmqxLBmw#jSpPx%2taR|dF{``&<@@V>KnUO1-(@PyOz0p(tR=MV~K z415Sq?2HeW{K^G?X7LsDv<-#; z5+93+p8d)`V*czemXwMZmRut!A^c>>joD-KpUrh*HkPnS(%S6Ug4^$*7@3j`bRgT$ z;!#_vXNiQj&HuIHZE_u1nYp|~@3>N^aX)?CdiKJ8dQFFMoVJhpV%Q#tIF?Rkyr1;P zgQ1==XVcF@rR!yBcEh=KcZ)2%kxWKHrjslQ?JAL`Ldwfz_A35N+MJD@JJSwomW!dZ zi(B165C&&pa1$7}z~nYq+yR@r;P4!{+=Cp?gU1Vy#~K%OxL<7^3OVR1)lG);|Iovn z{LM`Qn*jU3m{ZvE>jb+9(^}-qD=5gT1lJJw%HG3=@nN}9tu&jJdQIoPsWdCCdV{-% z^=7Nw;Q9S}wOX!`n7d!!Ydj$Cpi!^29yN)>NEX80gKDK#ZoHK_UG*Wtw($g$rHDM! zwqAcSwGOFeWYQN|-*A6+J)zwBUXB=8B;`N4Tq=%c_^Uw zb?}>0BMLOtrhy6J3}g|@JO(90gagdM$KUxM2q>?T!bQ*yRY2j;jx4H6jl#TPUNivCXm TR%C%ydcSztW+uDDuG;?t2p=l? delta 411 zcmZ22+{L5r#LLUY00d&q$KsM$7#JRdI4}U@GdKWovE4*e4IH&O9aT&WGVtFxW!YHSRP-HSX^A5UzCEWJd`C~1!S})Ggx_% zC`b=mQEG8%P6@K=$v0Rs7^5aTvI=WPu{r1Gl;-9|v3ur~q^749-D1j2xy2S-Qk0pO zUIcb5$N@$ClWSR(4TV7laugKh7o--IRD!*6i>)}dq$IVdNF1aL;R7&BX!1o?9Zo+@ wjv^+YEHD^2)h(k~ee+XNbBfrosRx^HlbfGXnv-hB2;>!ml<_bMF!C@105G>$0RR91 diff --git a/apps/cms/__pycache__/views.cpython-37.pyc b/apps/cms/__pycache__/views.cpython-37.pyc index 2f049967165481a6e02bbd328a2d0b8022c454f6..c7dfada11ffcdb7e7809d4d27718e18662c2fb02 100644 GIT binary patch literal 4407 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 delta 1351 zcmb7DO-~b16rDHIPKS2d!qBgQwqT9H8U#U&3ym6BxG)k4YT_(x3hx2c8K${21$M;f zQWMSFy3ikCjEVojor_r+cgBTVm)`pTQKKfdnbSMxoqON?>YLURx3G}UXEppheEa_1 zE&F+)##+y(&hG^|FUK^lal^NRyq8yY$}a>(uc+*_KOBsBBTN&Fo5JB4Zap=;Q9i`8 zekmw>Wjq;uS>d@?jN3f_SbN00s$vSr6#1}XYKj>_#^Ixiaj$8-#P`aNHC`6R{jo=e zH;z<=SCOe6Fm+^V+(pJcU>aidev^-h@s|^P9K+S0>XZO-4N*s~`3pB88pur^a{Sne z)^2^KHngo|Xu%)I7wj6-;tPr%G`kMPt7XuA0$wY&-H4#Og-S0vd-LT3KU>eWbX{gih z{*`CRI!ADt;HXNKFjc-FUk{zXI!mW#2<8a>-IsZkT*l|1FO~uG*cbWNp4^civQvu; zJ?L3H^yC`uGFwtfwHf@Wqm=v^X~*jbqP~L)n)2yM7w{I4Ktg*se*1Bj_FuV+G#jd$11TB`woL#5e)zU diff --git a/apps/cms/forms.py b/apps/cms/forms.py index de7c6fa..98477f5 100644 --- a/apps/cms/forms.py +++ b/apps/cms/forms.py @@ -1,5 +1,6 @@ -from wtforms import Form, StringField, IntegerField +from wtforms import Form, StringField, IntegerField, ValidationError from wtforms.validators import Email, InputRequired, Length, EqualTo +from utils import clcache class BaseForm(Form): @@ -17,4 +18,16 @@ class LoginForm(BaseForm): class ResetPwdForm(BaseForm): oldpwd = StringField(validators=[Length(6, 20, message='密码长度应介于6-20')]) newpwd = StringField(validators=[Length(6, 20, message='密码长度应介于6-20')]) - newpwd2 = StringField(validators=[EqualTo("newpwd", message='两次输入密码不一致')]) \ No newline at end of file + newpwd2 = StringField(validators=[EqualTo("newpwd", message='两次输入密码不一致')]) + + +class ResetEmailForm(BaseForm): + email = StringField(validators=[Email(message='您的邮箱格式有误,请重新输入')]) + captcha = StringField(validators=[Length(4, 4, message='请输入4位验证码')]) + + def validate_captcha(self, form): + captcha = self.captcha.data + email = self.email.data + redis_captcha = clcache.get_captcha(email) + if not redis_captcha or captcha.lower() != redis_captcha.lower(): + raise ValidationError('邮箱验证码错误') \ No newline at end of file diff --git a/apps/cms/models.py b/apps/cms/models.py index a5b9140..64757ef 100644 --- a/apps/cms/models.py +++ b/apps/cms/models.py @@ -30,4 +30,47 @@ class CMSUser(db.Model): def check_password(self, raw_password): '''验证密码是否正确''' result = check_password_hash(self.password, raw_password) - return result \ No newline at end of file + return result + + +class CMSPermission(object): + # 255二进制表示所有权限 + ALL_PERMISSION = 0b11111111 + + # 访问权限 + VISITOR = 0b00000001 + + # 管理帖子权限 + POSTER = 0b00000010 + + # 管理评论权限 + COMMENTER = 0b00000100 + + # 管理板块 + BOARDER = 0b00001000 + + # 管理前台用户 + FRONTUSER = 0b00010000 + + # 管理前台用户 + CMSUSER = 0b00100000 + + # 管理前台用户 + ADMINER = 0b01000000 + + +cms_role_user = db.Table( + 'cms_role_user', + db.Column('cms_role_id', db.Integer, db.ForeignKey('cms_role.id'), primary_key=True), + db.Column('cms_user_id', db.Integer, db.ForeignKey('cms_user.id'), primary_key=True) +) + + +class CMSRole(db.Model): + id = db.Column(db.Integer, primary_key=True, autoincrement=True) + name = db.Column(db.String(50), nullable=False) + desc = db.Column(db.String(200), nullable=False) + create_time = db.Column(db.DateTime, default=datetime.now()) + permissions = db.Column(db.Integer, default=CMSPermission.VISITOR) + + users = db.relationship('CMSUser', secondary=cms_role_user, backref='roles') \ No newline at end of file diff --git a/apps/cms/views.py b/apps/cms/views.py index e959033..7b90893 100644 --- a/apps/cms/views.py +++ b/apps/cms/views.py @@ -1,8 +1,9 @@ from flask import Blueprint, render_template, views, request, redirect, url_for, session, g -from apps.cms.forms import LoginForm, ResetPwdForm +from flask_mail import Message +from apps.cms.forms import LoginForm, ResetPwdForm, ResetEmailForm from apps.cms.models import CMSUser -from exts import db -from utils import restful +from exts import db, mail +from utils import restful, random_captcha, clcache # from .decorators import login_required # .代表当前路径 @@ -87,9 +88,35 @@ class ResetEmailView(views.MethodView): return render_template('cms/cms_resetemail.html') def post(self): - pass + form = ResetEmailForm(request.form) + if form.validate(): + email = form.email.data + # 修改用户邮箱 + g.cms_user.email = email + db.session.commit() + return restful.success() + else: + return restful.params_error(form.get_error()) + + +class EmailCaptchaView(views.MethodView): + def get(self): + email = request.args.get('email') + if not email: + return restful.params_error('请传递邮箱参数') + # 发送邮件验证码,可以是4位或6位的数字与英文组合 + captcha = random_captcha.get_random_captcha(4) + try: + message = Message('熊熊论坛验证码', recipients=[email], body='您正在进行更改邮箱验证,验证码是%s,5分钟内有效,请及时输入、注意保密。' % captcha) + mail.send(message) + except Exception as e: + print(e.args[0]) + return restful.server_error('邮件发送异常,请检查重试') + clcache.save_captcha(email, captcha) + return restful.success(message='邮件发送成功,请注意接收验证码') cms_bp.add_url_rule('/login/', view_func=LoginView.as_view('login')) cms_bp.add_url_rule('/resetpwd/', view_func=ResetPwdView.as_view('resetpwd')) cms_bp.add_url_rule('/resetemail/', view_func=ResetEmailView.as_view('resetemail')) +cms_bp.add_url_rule('/email_captcha/', view_func=EmailCaptchaView.as_view('email_captcha')) diff --git a/bbs.py b/bbs.py index 75d952a..d96161d 100644 --- a/bbs.py +++ b/bbs.py @@ -6,7 +6,7 @@ from flask import Flask from flask_wtf import CSRFProtect -from exts import db +from exts import db, mail from apps.cms.views import cms_bp from apps.front.views import front_bp import config @@ -15,8 +15,8 @@ import config app = Flask(__name__) CSRFProtect(app) app.config.from_object(config) -app.config['TEMPLATE_AUTO_RELOAD'] = True db.init_app(app) +mail.init_app(app) app.register_blueprint(cms_bp) app.register_blueprint(front_bp) diff --git a/config.py b/config.py index ec2cd3e..034f12e 100644 --- a/config.py +++ b/config.py @@ -8,10 +8,24 @@ PASSWORD = 'root' DATABASE = 'flask_bbs' DB_URL = 'mysql+mysqlconnector://{}:{}@{}:{}/{}?charset=utf8'.format(USERNAME, PASSWORD, HOSTNAME, PORT, DATABASE) +TEMPLATE_AUTO_RELOAD = True SQLALCHEMY_DATABASE_URI = DB_URL SQLALCHEMY_TRACK_MODIFICATIONS = False SQLALCHEMY_POOL_RECYCLE = 280 SQLALCHEMY_POOL_SIZE = 20 # 设置密钥 -SECRET_KEY = os.urandom(15) \ No newline at end of file +SECRET_KEY = os.urandom(15) + +# 发送邮箱服务地址 +MAIL_SERVER = 'smtp.qq.com' +# 邮箱端口,为587或465,为587时TLS设置为True,为465时SSL设置为True +MAIL_PORT = 587 +MAIL_USE_TLS = True +# MAIL_USE_SSL = True # MAIL_PORT为465时设置此项 +# 用户名可以为你的邮箱,需要自行添加 +MAIL_USERNAME = '123456789@qq.com' +# 邮箱密码,不是邮箱账号密码,而是第三方客户端登录使用的授权码,需要自行获取 +MAIL_PASSWORD = 'xxxxxxxxxxxxxxxx' +# 发送者即你的邮箱,需要自行添加 +MAIL_DEFAULT_SENDER = '123456789@qq.com' \ No newline at end of file diff --git a/exts.py b/exts.py index 2e1eeb6..2f87add 100644 --- a/exts.py +++ b/exts.py @@ -1,3 +1,6 @@ from flask_sqlalchemy import SQLAlchemy +from flask_mail import Mail -db = SQLAlchemy() \ No newline at end of file +db = SQLAlchemy() + +mail = Mail() \ No newline at end of file diff --git a/manage.py b/manage.py index fe652a7..5c32591 100644 --- a/manage.py +++ b/manage.py @@ -2,7 +2,7 @@ from flask_script import Manager from bbs import app from flask_migrate import Migrate, MigrateCommand from exts import db -from apps.cms.models import CMSUser +from apps.cms.models import CMSUser, CMSRole manager = Manager(app) Migrate(app, db) diff --git a/migrations/versions/__pycache__/ba80d307aa21_.cpython-37.pyc b/migrations/versions/__pycache__/ba80d307aa21_.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..108b9ec3bcb75c7d59248158beaaefedf21c4ec3 GIT binary patch literal 1268 zcmZux&2Jk;6yMoh@2=N&le7^6#KAY@LnGHAxV54R#UWBf6-BtcSSwcJeZyv({V+4* zRPL#&io_*CmEge5zQL6%h%+btfVrYn%^$#>H)}f|h#Bph_kQ!{y*F=u+Py}@H*jq1 zs;}->4C8NYtcHooXZVR-6krSuAYi5>GlwS8x|Lc(8|+~PDnkdXp^Kjf4!Ez4VHG^6 z;_8DnFk1eLW0sBOw3#s>Xv}>7OLm%wq{y3(_Iu3{z2AoIc9+u5y~Pd_z2?_l`bl>L zBTBpX{61$?vgSUDUbEBgwC}b*z1!YFwYR;~>pa-nZtrxv4}AXuYc*O#nZ@{USic@w z)vrg4wBKsfQR(9+{z4&*837{AXBL>!oY`{&EU=++W|x?QvH~u6X9UsenN^~GiPrvu z*73Yko?rPjE+dx6%ms5!<}O)ey;a6qTl!o@U%!dWJXnhfY{X=)EA(I;t=mh>g*8~8 zn{x->$iUv;IaFShiI5j5Q)U8B4qB#a(1|RPJmM^4xl~?0NmDvP2Ro-3yXasWu!l~{ z@>m|X2zL=sHZT!g{HfI%p2VjJWs)&f8#A6ILO-Waja9C2A{ZamF3kiMhK9ogUR>^M ztqi?`Mytv-^HhD6qb$r6R5|@3on*OkALWw8j4Nj#d6LJ<)4X`1YuP;FNk;kf3pVXz zIg--^@3(nSaF)dR4fGd-zmIuJ@y`#a^?SinEI|a1SzeqL!9EiwvKR*gIe}?#@$$EK zf4q77<4^Bi{dzQ&$3=er`^)q1-<*H@^V`{X!2${ou#w?F(&!|7T*OKA`To=3Af@6Y zJmSSO7RjZxw>Jo~B<57=t_7!EdcC=8WLQ - .form-container { - width: 300px; - } - + {% endblock %} {% block content %} diff --git a/templates/cms/cms_resetpwd.html b/templates/cms/cms_resetpwd.html index 515fc67..8acfd68 100644 --- a/templates/cms/cms_resetpwd.html +++ b/templates/cms/cms_resetpwd.html @@ -9,11 +9,6 @@ {% endblock %} {% block head %} - {% endblock %} diff --git a/utils/__pycache__/clcache.cpython-37.pyc b/utils/__pycache__/clcache.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0db45f82223afdd6daa0e05c45cea8e2b3a33475 GIT binary patch literal 770 zcma)4O=}ZD7@qygcS7w&|H6WJ77>xO_Ebu7?PXb9)|sK%W||2zvw=VksZ=OMEj=iD zOK&O^#gkC+hs@P(Oz`a8cQ&SY5qx3Zj~U*1pXZrrH=8vCmR9xSv4zlgQ!K3n$$ePz zHaLQa#ZZVS+OvpF9H?F5y>LUDG)b9M4z183RZ=@dp-bwd0nsB?fc(}Ry3v-dGL940 z;ZmhPZy@x@ceQIO?e@7)+9prJ6+$s5G!|6$c~4R~zX_PIV=e$Q(Sx-HOSZr%G_gi# zWR2`I2PRqBb=aI9AJ0ELpM5;|F*(T3-{eQ19#WD@-`1AUj-<+Ww9}8rQ1r=Pcns>6Hv z*KvMwnm>Ctog77rt#~72EDltHyYVL9P4R>EooIt4vKwy;zDKe8Q?=Vcl&O@-2s51E z4!zYM>V`}PG{#9^;Z9NpMA8O_Y+-0)5T!5^jVOg6<{cM;oEg~{Vq9LlEZARuInPgC zU+Lo8!d$AIU68{PRmcnS3)eJ9bvRlAFuE)OtU&&M0JfG>N`x}1=syOv7N^Tu*REz+ zVij`eGXKyog`P0)7}f(NQmhJE1&cxxVQ>`jkK?*x0r32qNg>!^Um*J^f;KB_pQ24>}9aNZZ zn)!J+^7!Su`TmRQ&B6Tbm+Is5#i!ll>8?hZ>9IOvaKm6=5EwiHbQ;>pf+XacNR??9 zVkXAAVdf}Nn$RI+=}<(JYkN~f2~?0IA8VTm#x;(#lcy=qv=fVmFp*e7RmRl^lwE)W zemw)MT=6y}&!o4;6R{<{9+x8}Qm?OaHu0*RuZ!=8^H;AIk3X+Z)KDa|Z#%Pt!`ajK z^Xa~KlJZycIQIK0pd)`xgb}^j+wfN7K#u(NOl)$hPF1(t_i`1*(mT0}PlHs^VQ@K} z=yu4J|9{$s_GBA?EE_N5v-N1<7H;G05@b78W*$l%*BAN+7hyp+uZ{)FV}8y2XK9{J Gll%b_da~*O literal 0 HcmV?d00001 diff --git a/utils/clcache.py b/utils/clcache.py new file mode 100644 index 0000000..93704d2 --- /dev/null +++ b/utils/clcache.py @@ -0,0 +1,18 @@ +import redis + +# 连接Redis数据库 +r = redis.StrictRedis(host='localhost', port=6379, db=0, decode_responses=True) + + +def save_captcha(key, value, timeout=300): + '''把验证码存到Redis''' + return r.set(key, value, timeout) + + +def get_captcha(key): + '''从Redis中取验证码''' + return r.get(key) + + +def delete_captcha(key): + return r.delete(key) diff --git a/utils/random_captcha.py b/utils/random_captcha.py new file mode 100644 index 0000000..157e6d9 --- /dev/null +++ b/utils/random_captcha.py @@ -0,0 +1,14 @@ +import random + + +def get_random_captcha(num): + '''生成随机验证码''' + code = '' + for i in range(num): + num = str(random.randint(0, 9)) + upper = chr(random.randint(65, 90)) + lower = chr(random.randint(97, 122)) + lst = [num, upper, lower] + ret = random.choice(lst) + code = ''.join([code, ret]) + return code \ No newline at end of file -- GitLab