从头搭建一个flask鉴权系统之完结篇

简介: 用了几天的时间,写了一个简单的用户鉴权系统,同时也输出了一系列的总结文章,希望小伙伴儿们能喜欢。 从头搭建一个flask鉴权系统之登陆 从头搭建一个flask鉴权系统之角色 从头搭建一个flask鉴权系统之注册这一篇将会是本系列的最后一篇,让我一起来做个收尾,GO!

知识树


1.集成短信验证码

2.用户资料维护


短信发送demo


使用twilio发短信

我这里使用twilio提供的短信功能,它提供了一个免费的短信接口,让我们可以在完全free的状态下测试短信功能,同时也有对应的python库twilio来简化开发,只需要使用pip install twilio即可使用该公司提供的各种功能。有兴趣的同学可以移步官网查看:

https://www.twilio.com/

产生validate code

和前面产生确认邮件的token一样,这里也使用itsdangerous来加密code

def generate_code(expiration=3600):
     random_num = ''.join(str(i) for i in random.sample(range(0, 9), 4))
     s = Serializer(Config.SECRET_KEY, expiration)
    return s.dumps({'code': random_num})
 def decoding_code(code):
     s = Serializer(Config.SECRET_KEY)
     c = s.loads(code)
    return c['code']

然后是发送短信的代码,查看官网就可以获得,很简单,不多说了。

def sendsms(code, num):
    account_sid = os.environ.get('A_SID')
    auth_token = os.environ.get('A_TK')
    mytwilio_num = os.environ.get('T_NUM')
    client = Client(account_sid, auth_token)
    message = client.messages.create(
        from_=mytwilio_num,
        body=code,
        to=num)


集成短信功能到系统


新增两个表单,一个是发送verify code,一个是验证verify code

class LoginSMSCodeForm(FlaskForm):
    phonenumber = IntegerField('Your Phone Number', validators=[DataRequired()])
    submit = SubmitField('Send validate code')
class LoginSMSForm(FlaskForm):
    validatacode = IntegerField('Enter validate code')
    submit = SubmitField('Login')

新增两个路由函数,login_codesend和login_codeverify。分别处理两个表单的提交逻辑。

login_codesend函数,会像输入的手机号发送verify code,并把产生的code传给login_codeverify函数,用于比较。

@auth.route('/logincodesend/', methods=['GET', 'POST'])
 def login_codesend():
     codeform = LoginSMSCodeForm()
     if codeform.validate_on_submit():
         num = codeform.phonenumber.data
         user = UserPhone.query.filter_by(phone=num).first()
         if user is None:
             user = UserPhone(phone=num)
             db.session.add(user)
            db.session.commit()
        code = generate_code()
        decod_code = decoding_code(code)
        sendsms(decod_code, '+86' + str(num))
        flash('Have send a validate code to your phone')
        return redirect(url_for('.login_codeverify', code=code, num=num))
    return render_template('auth/logincodesend.html', form=codeform)

login_codeverify函数,比较拿到的verify code和用户输入的code,如果一样,则登陆成功。

@auth.route('/logincodeverify/<code>/<num>', methods=['GET', 'POST'])
 def login_codeverify(code, num):
     form = LoginSMSForm()
     code = decoding_code(code)
     if form.validate_on_submit():
         if str(form.validatacode.data) == code:
             webuser = WebUser.query.filter_by(phone=num).first()
             if webuser is None:
                 webuser = WebUser(username=num, phone=num, user_id=time.time(), confirmed=True)
                db.session.add(webuser)
                db.session.commit()
            phoneuser = UserPhone.query.filter_by(phone=num).first()
            if phoneuser:
                phoneuser.user_id = webuser.user_id
                db.session.add(phoneuser)
                db.session.commit()
                login_user(webuser)
                return redirect(url_for('main.index'))
        flash('Invalid verify code')
        return redirect(url_for('.login_codeverify', code=code, num=num))
    return render_template('auth/logincodeverify.html', form=form)


添加用户资料页


gravatar用户头像

使用gravatar,它可以把用户的Email和头像关联起来,快速生成用户头像图片,其中Email地址需要经过md5加密处理。

可以使用查询字符串的形式,在url中传入参数,来获取头像图片。

参数说明

参数名 说明
s 图片大小,单位为像素
r 图片级别,可选值有“g”,“pg”,“r”和“x”
d 没有注册Gavatar服务的用户使用的默认图片生成方式,例如“identicon”
fd 强制使用默认头像

URL例子:

http://secure.gravatar.com/avatar/ffd5c7d7bfcc8605aaa2d259e2590112?s=128&d=identicon&r=g

添加生成头像方法

在WebUser类中,添加生成头像的方法函数

    def gravatar(self, size=100, default='identicon', rating='g'):
         if request.is_secure:
             url = 'https://secure.gravatar.com/avatar'
         else:
             url = 'http://secure.gravatar.com/avatar'
         email = self.email or 'test@luobo.com'
         hash = self.avatar_hash or hashlib.md5(
             email.lower().encode('utf-8')).hexdigest()
         avatar = '{url}/{hash}?s={size}&d={default}&r={rating}'.format(
            url=url, hash=hash, size=size, default=default, rating=rating
        )
        return avatar

丰富用户资料字段

为WebUser新增三个字段,以丰富用户资料

    nickname = db.Column(db.String(64))
    about_me = db.Column(db.Text())
    avatar_hash = db.Column(db.String(32))

添加路由函数

添加展示用户profile的函数,这里对使用GitHub登陆的用户做了判断,优先展示GitHub的头像和用户名

@main.route('/user/<username>', methods=['GET', 'POST'])
 @login_required
 def user(username):
     user = WebUser.query.filter_by(username=username).first()
     if user is None:
         abort(404)
     if 'userid' in session:
         thirduser = ThirdOAuth.query.filter_by(user_id=session['userid']).first()
         if thirduser:
            response = github.get('user', access_token=thirduser.oauth_access_token)
            avatar = response['avatar_url']
            gituser = response['login']
            return render_template('user.html', user=user, avatar=avatar, gituser=gituser)
    return render_template('user.html', user=user, avatar=None, gituser=None)


编辑用户资料


定义表单,包括username,nickname和about_me,用于提供给用户做修改

class EditProfileForm(FlaskForm):
    username = StringField('Username', validators=[Length(0, 64)])
    nickname = StringField('Nickname', validators=[Length(0, 64)])
    about_me = TextAreaField('About me')
    submit = SubmitField('Submit')

然后在路由函数中判断,如果username存在且不是当前用户时,不能修改username,如果修改的username是唯一,那么更新数据库。

@main.route('/edit-profile', methods=['GET', 'POST'])
 @login_required
 def edit_profile():
     form = EditProfileForm()
     if form.validate_on_submit():
         username = form.username.data
         if WebUser.query.filter_by(username=username).first() and username != current_user.username:
             flash('This username has been used')
             return redirect(url_for('main.edit_profile'))
        current_user.username = form.username.data
        current_user.nickname = form.nickname.data
        current_user.about_me = form.about_me.data
        db.session.add(current_user)
        db.session.commit()
        flash('Your profile has been updated')
        return redirect(url_for('.user', username=current_user.username))
    form.username.data = current_user.username
    form.nickname.data = current_user.nickname
    form.about_me.data = current_user.about_me
    return render_template('edit_profile.html', form=form)


页面演示


我将完整的代码上传到GitHub上了,有兴趣的同学可以戳这里:

https://github.com/zhouwei713/flask-webauth

另外还配置了一个演示web,地址为:

https://luobodazahui.top/

同时还创建了几个测试用户,可以来体验

普通用户1: user1@luobo.com/test1

普通用户2: user2@luobo.com/test2

管理员用户1: admin1@luobo.com/admin1

管理员用户2: admin2@luobo.com/admin2

也可以点击“阅读原文”进入

感兴趣的同学可以来玩玩

相关文章
|
1月前
|
数据采集 自然语言处理 数据可视化
优秀python系统案例】基于python Flask的电影票房数据爬取与可视化系统的设计与实现
本文介绍了一个基于Python Flask框架开发的电影票房数据爬取与可视化系统,该系统利用网络爬虫技术从豆瓣电影网站抓取数据,通过Python进行数据处理和分析,并采用ECharts等库实现数据的可视化展示,为电影行业从业者提供决策支持。
优秀python系统案例】基于python Flask的电影票房数据爬取与可视化系统的设计与实现
|
1月前
|
数据采集 数据可视化 关系型数据库
【优秀python web设计】基于Python flask的猫眼电影可视化系统,可视化用echart,前端Layui,数据库用MySQL,包括爬虫
本文介绍了一个基于Python Flask框架、MySQL数据库和Layui前端框架的猫眼电影数据采集分析与可视化系统,该系统通过爬虫技术采集电影数据,利用数据分析库进行处理,并使用Echart进行数据的可视化展示,以提供全面、准确的电影市场分析结果。
|
1月前
|
机器学习/深度学习 数据采集 数据可视化
【优秀python系统毕设】基于Python flask的气象数据可视化系统设计与实现,有LSTM算法预测气温
本文介绍了一个基于Python Flask框架开发的气象数据可视化系统,该系统集成了数据获取、处理、存储、LSTM算法气温预测以及多种数据可视化功能,旨在提高气象数据的利用价值并推动气象领域的发展。
|
1月前
|
数据采集 存储 数据可视化
基于Python flask的猫眼电影票房数据分析可视化系统,可以定制可视化
本文介绍了一个基于Python Flask框架开发的猫眼电影票房数据分析可视化系统,该系统集成了数据爬取、存储处理、可视化展示和用户交互功能,使用户能够直观地分析和展示电影票房数据,具有高度定制性。
基于Python flask的猫眼电影票房数据分析可视化系统,可以定制可视化
|
1月前
|
机器学习/深度学习 数据采集 存储
基于Python+flask+echarts的气象数据采集与分析系统,可实现lstm算法进行预测
本文介绍了一个基于Python、Flask和Echarts的气象数据采集与分析系统,该系统集成了LSTM算法进行数据预测,并提供了实时数据监测、历史数据查询、数据可视化以及用户权限管理等功能。
|
1月前
|
机器学习/深度学习 算法 数据可视化
基于Python flask的豆瓣电影数据分析可视化系统,功能多,LSTM算法+注意力机制实现情感分析,准确率高达85%
本文介绍了一个基于Python Flask框架的豆瓣电影数据分析可视化系统,该系统集成了LSTM算法和注意力机制进行情感分析,准确率高达85%,提供了多样化的数据分析和情感识别功能,旨在帮助用户深入理解电影市场和观众喜好。
|
1月前
|
监控 数据可视化 算法
基于朴素贝叶斯算法的微博舆情监控系统,flask后端,可视化丰富
本文介绍了一个基于朴素贝叶斯算法和Python技术栈的微博舆情监控系统,该系统使用Flask作为后端框架,通过数据爬取、清洗、情感分析和可视化等手段,为用户提供丰富的舆情分析和监测功能。
|
2月前
|
监控 前端开发 API
实战指南:使用Python Flask与WebSocket实现高效的前后端分离实时系统
【7月更文挑战第18天】构建实时Web应用,如聊天室,可借助Python的Flask和WebSocket。安装Flask及Flask-SocketIO库,创建Flask应用,处理WebSocket事件。前端模板通过Socket.IO库连接服务器,发送和接收消息。运行应用,实现实时通信。此示例展现了Flask结合WebSocket实现前后端实时交互的能力。
333 3
|
3月前
|
开发框架 数据库 开发者
Web开发新境界:用Python玩转Django和Flask!
【6月更文挑战第12天】Python的Web开发框架Django和Flask各有千秋。Django是全能型框架,适合快速开发大型应用,提供ORM、模板引擎、URL路由和后台管理等全面功能。Flask则轻量级且灵活,适用于小型到中型应用,以其简单易用、高度可扩展和灵活路由著称。两者结合使用,能应对各种Web开发需求。
63 5
|
3月前
|
关系型数据库 MySQL 数据库
如何使用Python的Flask框架来构建一个简单的Web应用
如何使用Python的Flask框架来构建一个简单的Web应用
78 0